clang 22.0.0git
Builtins.cpp
Go to the documentation of this file.
1//===--- Builtins.cpp - Builtin function implementation -------------------===//
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// This file implements various things for builtin functions.
10//
11//===----------------------------------------------------------------------===//
12
18#include "llvm/ADT/StringRef.h"
19using namespace clang;
20
21const char *HeaderDesc::getName() const {
22 switch (ID) {
23#define HEADER(ID, NAME) \
24 case ID: \
25 return NAME;
26#include "clang/Basic/BuiltinHeaders.def"
27#undef HEADER
28 };
29 llvm_unreachable("Unknown HeaderDesc::HeaderID enum");
30}
31
32static constexpr unsigned NumBuiltins = Builtin::FirstTSBuiltin;
33
34#define GET_BUILTIN_STR_TABLE
35#include "clang/Basic/Builtins.inc"
36#undef GET_BUILTIN_STR_TABLE
37
38static constexpr Builtin::Info BuiltinInfos[] = {
39 Builtin::Info{}, // No-builtin info entry.
40#define GET_BUILTIN_INFOS
41#include "clang/Basic/Builtins.inc"
42#undef GET_BUILTIN_INFOS
43};
44static_assert(std::size(BuiltinInfos) == NumBuiltins);
45
46std::pair<const Builtin::InfosShard &, const Builtin::Info &>
47Builtin::Context::getShardAndInfo(unsigned ID) const {
48 assert((ID < (Builtin::FirstTSBuiltin + NumTargetBuiltins +
49 NumAuxTargetBuiltins)) &&
50 "Invalid builtin ID!");
51
52 ArrayRef<InfosShard> Shards = BuiltinShards;
53 if (isAuxBuiltinID(ID)) {
54 Shards = AuxTargetShards;
56 } else if (ID >= Builtin::FirstTSBuiltin) {
57 Shards = TargetShards;
59 }
60
61 // Loop over the shards to find the one matching this ID. We don't expect to
62 // have many shards and so its better to search linearly than with a binary
63 // search.
64 for (const auto &Shard : Shards) {
65 if (ID < Shard.Infos.size()) {
66 return {Shard, Shard.Infos[ID]};
67 }
68
69 ID -= Shard.Infos.size();
70 }
71 llvm_unreachable("Invalid target builtin shard structure!");
72}
73
74std::string Builtin::Info::getName(const Builtin::InfosShard &Shard) const {
75 return (Twine(Shard.NamePrefix) + (*Shard.Strings)[Offsets.Name]).str();
76}
77
78/// Return the identifier name for the specified builtin,
79/// e.g. "__builtin_abs".
80std::string Builtin::Context::getName(unsigned ID) const {
81 const auto &[Shard, I] = getShardAndInfo(ID);
82 return I.getName(Shard);
83}
84
85std::string Builtin::Context::getQuotedName(unsigned ID) const {
86 const auto &[Shard, I] = getShardAndInfo(ID);
87 return (Twine("'") + Shard.NamePrefix + (*Shard.Strings)[I.Offsets.Name] +
88 "'")
89 .str();
90}
91
92const char *Builtin::Context::getTypeString(unsigned ID) const {
93 const auto &[Shard, I] = getShardAndInfo(ID);
94 return (*Shard.Strings)[I.Offsets.Type].data();
95}
96
97const char *Builtin::Context::getAttributesString(unsigned ID) const {
98 const auto &[Shard, I] = getShardAndInfo(ID);
99 return (*Shard.Strings)[I.Offsets.Attributes].data();
100}
101
102const char *Builtin::Context::getRequiredFeatures(unsigned ID) const {
103 const auto &[Shard, I] = getShardAndInfo(ID);
104 return (*Shard.Strings)[I.Offsets.Features].data();
105}
106
108
110 const TargetInfo *AuxTarget) {
111 assert(TargetShards.empty() && "Already initialized target?");
112 assert(NumTargetBuiltins == 0 && "Already initialized target?");
113 TargetShards = Target.getTargetBuiltins();
114 for (const auto &Shard : TargetShards)
115 NumTargetBuiltins += Shard.Infos.size();
116 if (AuxTarget) {
117 AuxTargetShards = AuxTarget->getTargetBuiltins();
118 for (const auto &Shard : AuxTargetShards)
119 NumAuxTargetBuiltins += Shard.Infos.size();
120 }
121}
122
123bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) {
124 bool InStdNamespace = FuncName.consume_front("std-");
125 for (const auto &Shard : {InfosShard{&BuiltinStrings, BuiltinInfos}})
126 if (llvm::StringRef FuncNameSuffix = FuncName;
127 FuncNameSuffix.consume_front(Shard.NamePrefix))
128 for (const auto &I : Shard.Infos)
129 if (FuncNameSuffix == (*Shard.Strings)[I.Offsets.Name] &&
130 (bool)strchr((*Shard.Strings)[I.Offsets.Attributes].data(), 'z') ==
131 InStdNamespace)
132 return strchr((*Shard.Strings)[I.Offsets.Attributes].data(), 'f') !=
133 nullptr;
134
135 return false;
136}
137
138/// Is this builtin supported according to the given language options?
139static bool builtinIsSupported(const llvm::StringTable &Strings,
140 const Builtin::Info &BuiltinInfo,
141 const LangOptions &LangOpts) {
142 auto AttributesStr = Strings[BuiltinInfo.Offsets.Attributes];
143
144 /* Builtins Unsupported */
145 if (LangOpts.NoBuiltin && strchr(AttributesStr.data(), 'f') != nullptr)
146 return false;
147 /* CorBuiltins Unsupported */
148 if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG))
149 return false;
150 /* MathBuiltins Unsupported */
151 if (LangOpts.NoMathBuiltin && BuiltinInfo.Header.ID == HeaderDesc::MATH_H)
152 return false;
153 /* GnuMode Unsupported */
154 if (!LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG))
155 return false;
156 /* MSMode Unsupported */
157 if (!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG))
158 return false;
159 /* HLSLMode Unsupported */
160 if (!LangOpts.HLSL && (BuiltinInfo.Langs & HLSL_LANG))
161 return false;
162 /* ObjC Unsupported */
163 if (!LangOpts.ObjC && BuiltinInfo.Langs == OBJC_LANG)
164 return false;
165 /* OpenCLC Unsupported */
166 if (!LangOpts.OpenCL && (BuiltinInfo.Langs & ALL_OCL_LANGUAGES))
167 return false;
168 /* OpenCL GAS Unsupported */
169 if (!LangOpts.OpenCLGenericAddressSpace && (BuiltinInfo.Langs & OCL_GAS))
170 return false;
171 /* OpenCL Pipe Unsupported */
172 if (!LangOpts.OpenCLPipes && (BuiltinInfo.Langs & OCL_PIPE))
173 return false;
174
175 // Device side enqueue is not supported until OpenCL 2.0. In 2.0 and higher
176 // support is indicated with language option for blocks.
177
178 /* OpenCL DSE Unsupported */
179 if ((LangOpts.getOpenCLCompatibleVersion() < 200 || !LangOpts.Blocks) &&
180 (BuiltinInfo.Langs & OCL_DSE))
181 return false;
182 /* OpenMP Unsupported */
183 if (!LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG)
184 return false;
185 /* CUDA Unsupported */
186 if (!LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG)
187 return false;
188 /* CPlusPlus Unsupported */
189 if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
190 return false;
191 /* consteval Unsupported */
192 if (!LangOpts.CPlusPlus20 && strchr(AttributesStr.data(), 'G') != nullptr)
193 return false;
194 /* C23 unsupported */
195 if (!LangOpts.C23 && BuiltinInfo.Langs == C23_LANG)
196 return false;
197 return true;
198}
199
200static bool isBuiltinConstForTriple(unsigned BuiltinID, llvm::Triple Trip) {
201 // There's a special case with the fma builtins where they are always const
202 // if the target environment is GNU or the target is OS is Windows and we're
203 // targeting the MSVCRT.dll environment.
204 // FIXME: This list can be become outdated. Need to find a way to get it some
205 // other way.
206 switch (BuiltinID) {
207 case Builtin::BI__builtin_fma:
208 case Builtin::BI__builtin_fmaf:
209 case Builtin::BI__builtin_fmal:
210 case Builtin::BI__builtin_fmaf16:
211 case Builtin::BIfma:
212 case Builtin::BIfmaf:
213 case Builtin::BIfmal: {
214 if (Trip.isGNUEnvironment() || Trip.isOSMSVCRT())
215 return true;
216 break;
217 }
218 default:
219 break;
220 }
221
222 return false;
223}
224
226 unsigned BuiltinID, llvm::Triple Trip, std::optional<bool> ErrnoOverwritten,
227 bool MathErrnoEnabled, bool HasOptNoneAttr,
228 bool IsOptimizationEnabled) const {
229
230 // True if we are compiling at -O2 and errno has been disabled
231 // using the '#pragma float_control(precise, off)', and
232 // attribute opt-none hasn't been seen.
233 bool ErrnoOverridenToFalseWithOpt = ErrnoOverwritten.has_value() &&
234 !ErrnoOverwritten.value() &&
235 !HasOptNoneAttr && IsOptimizationEnabled;
236
237 // There are LLVM math intrinsics/instructions corresponding to math library
238 // functions except the LLVM op will never set errno while the math library
239 // might. Also, math builtins have the same semantics as their math library
240 // twins. Thus, we can transform math library and builtin calls to their
241 // LLVM counterparts if the call is marked 'const' (known to never set errno).
242 // In case FP exceptions are enabled, the experimental versions of the
243 // intrinsics model those.
244 bool ConstAlways =
245 isConst(BuiltinID) || isBuiltinConstForTriple(BuiltinID, Trip);
246
247 bool ConstWithoutErrnoAndExceptions =
249 bool ConstWithoutExceptions = isConstWithoutExceptions(BuiltinID);
250
251 // ConstAttr is enabled in fast-math mode. In fast-math mode, math-errno is
252 // disabled.
253 // Math intrinsics are generated only when math-errno is disabled. Any pragmas
254 // or attributes that affect math-errno should prevent or allow math
255 // intrinsics to be generated. Intrinsics are generated:
256 // 1- In fast math mode, unless math-errno is overriden
257 // via '#pragma float_control(precise, on)', or via an
258 // 'attribute__((optnone))'.
259 // 2- If math-errno was enabled on command line but overriden
260 // to false via '#pragma float_control(precise, off))' and
261 // 'attribute__((optnone))' hasn't been used.
262 // 3- If we are compiling with optimization and errno has been disabled
263 // via '#pragma float_control(precise, off)', and
264 // 'attribute__((optnone))' hasn't been used.
265
266 bool ConstWithoutErrnoOrExceptions =
267 ConstWithoutErrnoAndExceptions || ConstWithoutExceptions;
268 bool GenerateIntrinsics =
269 (ConstAlways && !HasOptNoneAttr) ||
270 (!MathErrnoEnabled &&
271 !(ErrnoOverwritten.has_value() && ErrnoOverwritten.value()) &&
272 !HasOptNoneAttr);
273 if (!GenerateIntrinsics) {
274 GenerateIntrinsics =
275 ConstWithoutErrnoOrExceptions && !ConstWithoutErrnoAndExceptions;
276 if (!GenerateIntrinsics)
277 GenerateIntrinsics =
278 ConstWithoutErrnoOrExceptions &&
279 (!MathErrnoEnabled &&
280 !(ErrnoOverwritten.has_value() && ErrnoOverwritten.value()) &&
281 !HasOptNoneAttr);
282 if (!GenerateIntrinsics)
283 GenerateIntrinsics =
284 ConstWithoutErrnoOrExceptions && ErrnoOverridenToFalseWithOpt;
285 }
286
287 return GenerateIntrinsics;
288}
289
290/// initializeBuiltins - Mark the identifiers for all the builtins with their
291/// appropriate builtin ID # and mark any non-portable builtin identifiers as
292/// such.
294 const LangOptions &LangOpts) {
295 {
296 unsigned ID = 0;
297 // Step #1: mark all target-independent builtins with their ID's.
298 for (const auto &Shard : BuiltinShards)
299 for (const auto &I : Shard.Infos) {
300 // If this is a real builtin (ID != 0) and is supported, add it.
301 if (ID != 0 && builtinIsSupported(*Shard.Strings, I, LangOpts))
302 Table.get(I.getName(Shard)).setBuiltinID(ID);
303 ++ID;
304 }
305 assert(ID == FirstTSBuiltin && "Should have added all non-target IDs!");
306
307 // Step #2: Register target-specific builtins.
308 for (const auto &Shard : TargetShards)
309 for (const auto &I : Shard.Infos) {
310 if (builtinIsSupported(*Shard.Strings, I, LangOpts))
311 Table.get(I.getName(Shard)).setBuiltinID(ID);
312 ++ID;
313 }
314
315 // Step #3: Register target-specific builtins for AuxTarget.
316 for (const auto &Shard : AuxTargetShards)
317 for (const auto &I : Shard.Infos) {
318 Table.get(I.getName(Shard)).setBuiltinID(ID);
319 ++ID;
320 }
321 }
322
323 // Step #4: Unregister any builtins specified by -fno-builtin-foo.
324 for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
325 bool InStdNamespace = Name.consume_front("std-");
326 auto NameIt = Table.find(Name);
327 if (NameIt != Table.end()) {
328 unsigned ID = NameIt->second->getBuiltinID();
330 isInStdNamespace(ID) == InStdNamespace) {
331 NameIt->second->clearBuiltinID();
332 }
333 }
334 }
335}
336
338 const char *WidthPos = ::strchr(getAttributesString(ID), 'V');
339 if (!WidthPos)
340 return 0;
341
342 ++WidthPos;
343 assert(*WidthPos == ':' &&
344 "Vector width specifier must be followed by a ':'");
345 ++WidthPos;
346
347 char *EndPos;
348 unsigned Width = ::strtol(WidthPos, &EndPos, 10);
349 assert(*EndPos == ':' && "Vector width specific must end with a ':'");
350 return Width;
351}
352
353bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
354 bool &HasVAListArg, const char *Fmt) const {
355 assert(Fmt && "Not passed a format string");
356 assert(::strlen(Fmt) == 2 &&
357 "Format string needs to be two characters long");
358 assert(::toupper(Fmt[0]) == Fmt[1] &&
359 "Format string is not in the form \"xX\"");
360
361 const char *Like = ::strpbrk(getAttributesString(ID), Fmt);
362 if (!Like)
363 return false;
364
365 HasVAListArg = (*Like == Fmt[1]);
366
367 ++Like;
368 assert(*Like == ':' && "Format specifier must be followed by a ':'");
369 ++Like;
370
371 assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
372 FormatIdx = ::strtol(Like, nullptr, 10);
373 return true;
374}
375
376bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
377 bool &HasVAListArg) {
378 return isLike(ID, FormatIdx, HasVAListArg, "pP");
379}
380
381bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
382 bool &HasVAListArg) {
383 return isLike(ID, FormatIdx, HasVAListArg, "sS");
384}
385
387 SmallVectorImpl<int> &Encoding) const {
388 const char *CalleePos = ::strchr(getAttributesString(ID), 'C');
389 if (!CalleePos)
390 return false;
391
392 ++CalleePos;
393 assert(*CalleePos == '<' &&
394 "Callback callee specifier must be followed by a '<'");
395 ++CalleePos;
396
397 char *EndPos;
398 int CalleeIdx = ::strtol(CalleePos, &EndPos, 10);
399 assert(CalleeIdx >= 0 && "Callee index is supposed to be positive!");
400 Encoding.push_back(CalleeIdx);
401
402 while (*EndPos == ',') {
403 const char *PayloadPos = EndPos + 1;
404
405 int PayloadIdx = ::strtol(PayloadPos, &EndPos, 10);
406 Encoding.push_back(PayloadIdx);
407 }
408
409 assert(*EndPos == '>' && "Callback callee specifier must end with a '>'");
410 return true;
411}
412
414 return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start ||
415 ID == Builtin::BI__builtin_assume_aligned ||
418}
419
421 StringRef RequiredFeatures, const llvm::StringMap<bool> &TargetFetureMap) {
422 // Return true if the builtin doesn't have any required features.
423 if (RequiredFeatures.empty())
424 return true;
425 assert(!RequiredFeatures.contains(' ') && "Space in feature list");
426
427 TargetFeatures TF(TargetFetureMap);
428 return TF.hasRequiredFeatures(RequiredFeatures);
429}
static constexpr llvm::StringTable BuiltinStrings
Definition AMDGPU.cpp:101
static constexpr Builtin::Info BuiltinInfos[]
Definition Builtins.cpp:38
static bool builtinIsSupported(const llvm::StringTable &Strings, const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts)
Is this builtin supported according to the given language options?
Definition Builtins.cpp:139
static constexpr unsigned NumBuiltins
Definition Builtins.cpp:32
static bool isBuiltinConstForTriple(unsigned BuiltinID, llvm::Triple Trip)
Definition Builtins.cpp:200
Defines enum values for all the target-independent builtin functions.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
bool shouldGenerateFPMathIntrinsic(unsigned BuiltinID, llvm::Triple Trip, std::optional< bool > ErrnoOverwritten, bool MathErrnoEnabled, bool HasOptNoneAttr, bool IsOptimizationEnabled) const
Determine whether we can generate LLVM intrinsics for the given builtin ID, based on whether it has s...
Definition Builtins.cpp:225
std::string getQuotedName(unsigned ID) const
Return the identifier name for the specified builtin inside single quotes for a diagnostic,...
Definition Builtins.cpp:85
bool hasReferenceArgsOrResult(unsigned ID) const
Return true if this builtin has a result or any arguments which are reference types.
Definition Builtins.h:369
bool performsCallback(unsigned ID, llvm::SmallVectorImpl< int > &Encoding) const
Determine whether this builtin has callback behavior (see llvm::AbstractCallSites for details).
Definition Builtins.cpp:386
bool isAuxBuiltinID(unsigned ID) const
Return true if the builtin ID belongs exclusively to the AuxTarget, and false if it belongs to both p...
Definition Builtins.h:431
bool isConstWithoutErrnoAndExceptions(unsigned ID) const
Return true if this function has no side effects and doesn't read memory, except for possibly errno o...
Definition Builtins.h:401
static bool isBuiltinFunc(llvm::StringRef Name)
Returns true if this is a libc/libm function without the '__builtin_' prefix.
Definition Builtins.cpp:123
unsigned getRequiredVectorWidth(unsigned ID) const
Definition Builtins.cpp:337
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition Builtins.h:437
bool hasCustomTypechecking(unsigned ID) const
Determines whether this builtin has custom typechecking.
Definition Builtins.h:350
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Definition Builtins.cpp:80
void initializeBuiltins(IdentifierTable &Table, const LangOptions &LangOpts)
Mark the identifiers for all the builtins with their appropriate builtin ID # and mark any non-portab...
Definition Builtins.cpp:293
bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg)
Determine whether this builtin is like scanf in its formatting rules and, if so, set the index to the...
Definition Builtins.cpp:381
bool isInStdNamespace(unsigned ID) const
Determines whether this builtin is a C++ standard library function that lives in (possibly-versioned)...
Definition Builtins.h:336
bool canBeRedeclared(unsigned ID) const
Returns true if this is a builtin that can be redeclared.
Definition Builtins.cpp:413
const char * getAttributesString(unsigned ID) const
Get the attributes descriptor string for the specified builtin.
Definition Builtins.cpp:97
bool isPredefinedLibFunction(unsigned ID) const
Determines whether this builtin is a predefined libc/libm function, such as "malloc",...
Definition Builtins.h:314
bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg)
Determine whether this builtin is like printf in its formatting rules and, if so, set the index to th...
Definition Builtins.cpp:376
const char * getTypeString(unsigned ID) const
Get the type descriptor string for the specified builtin.
Definition Builtins.cpp:92
const char * getRequiredFeatures(unsigned ID) const
Definition Builtins.cpp:102
bool isConstWithoutExceptions(unsigned ID) const
Definition Builtins.h:405
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget)
Perform target-specific initialization.
Definition Builtins.cpp:109
bool isConst(unsigned ID) const
Return true if this function has no side effects and doesn't read memory.
Definition Builtins.h:276
TargetFeatures - This class is used to check whether the builtin function has the required target spe...
void setBuiltinID(unsigned ID)
Implements an efficient mapping from strings to IdentifierInfo nodes.
iterator find(StringRef Name) const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
Exposes information about the current target.
Definition TargetInfo.h:226
virtual llvm::SmallVector< Builtin::InfosShard > getTargetBuiltins() const =0
Return information about target-specific builtins for the current primary target, and info about whic...
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
The JSON file list parser is used to communicate input to InstallAPI.
@ MS_LANG
Definition Builtins.h:39
@ CUDA_LANG
Definition Builtins.h:41
@ OMP_LANG
Definition Builtins.h:40
@ CXX_LANG
Definition Builtins.h:37
@ OBJC_LANG
Definition Builtins.h:38
@ OCL_DSE
Definition Builtins.h:45
@ C23_LANG
Definition Builtins.h:48
@ ALL_OCL_LANGUAGES
Definition Builtins.h:46
@ HLSL_LANG
Definition Builtins.h:47
@ OCL_GAS
Definition Builtins.h:43
@ GNU_LANG
Definition Builtins.h:35
@ COR_LANG
Definition Builtins.h:42
@ OCL_PIPE
Definition Builtins.h:44
llvm::StringTable::Offset Attributes
Definition Builtins.h:85
The info used to represent each builtin.
Definition Builtins.h:79
HeaderDesc Header
Definition Builtins.h:91
LanguageID Langs
Definition Builtins.h:92
struct clang::Builtin::Info::StrOffsets Offsets
std::string getName(const InfosShard &Shard) const
Get the name for the builtin represented by this Info object.
Definition Builtins.cpp:74
A shard of a target's builtins string table and info.
Definition Builtins.h:132
const llvm::StringTable * Strings
Definition Builtins.h:133
llvm::StringLiteral NamePrefix
Definition Builtins.h:136
const char * getName() const
Definition Builtins.cpp:21
enum clang::HeaderDesc::HeaderID ID