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 /* OopenCL 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
200/// initializeBuiltins - Mark the identifiers for all the builtins with their
201/// appropriate builtin ID # and mark any non-portable builtin identifiers as
202/// such.
204 const LangOptions &LangOpts) {
205 {
206 unsigned ID = 0;
207 // Step #1: mark all target-independent builtins with their ID's.
208 for (const auto &Shard : BuiltinShards)
209 for (const auto &I : Shard.Infos) {
210 // If this is a real builtin (ID != 0) and is supported, add it.
211 if (ID != 0 && builtinIsSupported(*Shard.Strings, I, LangOpts))
212 Table.get(I.getName(Shard)).setBuiltinID(ID);
213 ++ID;
214 }
215 assert(ID == FirstTSBuiltin && "Should have added all non-target IDs!");
216
217 // Step #2: Register target-specific builtins.
218 for (const auto &Shard : TargetShards)
219 for (const auto &I : Shard.Infos) {
220 if (builtinIsSupported(*Shard.Strings, I, LangOpts))
221 Table.get(I.getName(Shard)).setBuiltinID(ID);
222 ++ID;
223 }
224
225 // Step #3: Register target-specific builtins for AuxTarget.
226 for (const auto &Shard : AuxTargetShards)
227 for (const auto &I : Shard.Infos) {
228 Table.get(I.getName(Shard)).setBuiltinID(ID);
229 ++ID;
230 }
231 }
232
233 // Step #4: Unregister any builtins specified by -fno-builtin-foo.
234 for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
235 bool InStdNamespace = Name.consume_front("std-");
236 auto NameIt = Table.find(Name);
237 if (NameIt != Table.end()) {
238 unsigned ID = NameIt->second->getBuiltinID();
239 if (ID != Builtin::NotBuiltin && isPredefinedLibFunction(ID) &&
240 isInStdNamespace(ID) == InStdNamespace) {
241 NameIt->second->clearBuiltinID();
242 }
243 }
244 }
245}
246
248 const char *WidthPos = ::strchr(getAttributesString(ID), 'V');
249 if (!WidthPos)
250 return 0;
251
252 ++WidthPos;
253 assert(*WidthPos == ':' &&
254 "Vector width specifier must be followed by a ':'");
255 ++WidthPos;
256
257 char *EndPos;
258 unsigned Width = ::strtol(WidthPos, &EndPos, 10);
259 assert(*EndPos == ':' && "Vector width specific must end with a ':'");
260 return Width;
261}
262
263bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
264 bool &HasVAListArg, const char *Fmt) const {
265 assert(Fmt && "Not passed a format string");
266 assert(::strlen(Fmt) == 2 &&
267 "Format string needs to be two characters long");
268 assert(::toupper(Fmt[0]) == Fmt[1] &&
269 "Format string is not in the form \"xX\"");
270
271 const char *Like = ::strpbrk(getAttributesString(ID), Fmt);
272 if (!Like)
273 return false;
274
275 HasVAListArg = (*Like == Fmt[1]);
276
277 ++Like;
278 assert(*Like == ':' && "Format specifier must be followed by a ':'");
279 ++Like;
280
281 assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
282 FormatIdx = ::strtol(Like, nullptr, 10);
283 return true;
284}
285
286bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
287 bool &HasVAListArg) {
288 return isLike(ID, FormatIdx, HasVAListArg, "pP");
289}
290
291bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
292 bool &HasVAListArg) {
293 return isLike(ID, FormatIdx, HasVAListArg, "sS");
294}
295
297 SmallVectorImpl<int> &Encoding) const {
298 const char *CalleePos = ::strchr(getAttributesString(ID), 'C');
299 if (!CalleePos)
300 return false;
301
302 ++CalleePos;
303 assert(*CalleePos == '<' &&
304 "Callback callee specifier must be followed by a '<'");
305 ++CalleePos;
306
307 char *EndPos;
308 int CalleeIdx = ::strtol(CalleePos, &EndPos, 10);
309 assert(CalleeIdx >= 0 && "Callee index is supposed to be positive!");
310 Encoding.push_back(CalleeIdx);
311
312 while (*EndPos == ',') {
313 const char *PayloadPos = EndPos + 1;
314
315 int PayloadIdx = ::strtol(PayloadPos, &EndPos, 10);
316 Encoding.push_back(PayloadIdx);
317 }
318
319 assert(*EndPos == '>' && "Callback callee specifier must end with a '>'");
320 return true;
321}
322
324 return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start ||
325 ID == Builtin::BI__builtin_assume_aligned ||
326 (!hasReferenceArgsOrResult(ID) && !hasCustomTypechecking(ID)) ||
327 isInStdNamespace(ID);
328}
329
331 StringRef RequiredFeatures, const llvm::StringMap<bool> &TargetFetureMap) {
332 // Return true if the builtin doesn't have any required features.
333 if (RequiredFeatures.empty())
334 return true;
335 assert(!RequiredFeatures.contains(' ') && "Space in feature list");
336
337 TargetFeatures TF(TargetFetureMap);
338 return TF.hasRequiredFeatures(RequiredFeatures);
339}
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
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.
llvm::MachO::Target Target
Definition: MachO.h:51
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 performsCallback(unsigned ID, llvm::SmallVectorImpl< int > &Encoding) const
Determine whether this builtin has callback behavior (see llvm::AbstractCallSites for details).
Definition: Builtins.cpp:296
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:414
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:247
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition: Builtins.h:420
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:203
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:291
bool canBeRedeclared(unsigned ID) const
Returns true if this is a builtin that can be redeclared.
Definition: Builtins.cpp:323
const char * getAttributesString(unsigned ID) const
Get the attributes descriptor string for the specified builtin.
Definition: Builtins.cpp:97
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:286
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
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget)
Perform target-specific initialization.
Definition: Builtins.cpp:109
TargetFeatures - This class is used to check whether the builtin function has the required tagert 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.
iterator end() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:434
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
Definition: LangOptions.h:501
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
Definition: LangOptions.cpp:65
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:38
@ CUDA_LANG
Definition: Builtins.h:40
@ OMP_LANG
Definition: Builtins.h:39
@ CXX_LANG
Definition: Builtins.h:36
@ OBJC_LANG
Definition: Builtins.h:37
@ OCL_DSE
Definition: Builtins.h:44
@ C23_LANG
Definition: Builtins.h:47
@ ALL_OCL_LANGUAGES
Definition: Builtins.h:45
@ HLSL_LANG
Definition: Builtins.h:46
@ OCL_GAS
Definition: Builtins.h:42
@ GNU_LANG
Definition: Builtins.h:34
@ COR_LANG
Definition: Builtins.h:41
@ OCL_PIPE
Definition: Builtins.h:43
llvm::StringTable::Offset Attributes
Definition: Builtins.h:84
The info used to represent each builtin.
Definition: Builtins.h:78
HeaderDesc Header
Definition: Builtins.h:90
LanguageID Langs
Definition: Builtins.h:91
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:131
const llvm::StringTable * Strings
Definition: Builtins.h:132
llvm::StringLiteral NamePrefix
Definition: Builtins.h:135
const char * getName() const
Definition: Builtins.cpp:21
enum clang::HeaderDesc::HeaderID ID