clang  15.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 
13 #include "clang/Basic/Builtins.h"
14 #include "BuiltinTargetFeatures.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "llvm/ADT/StringRef.h"
19 using namespace clang;
20 
21 static const Builtin::Info BuiltinInfo[] = {
22  { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,nullptr},
23 #define BUILTIN(ID, TYPE, ATTRS) \
24  { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
25 #define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \
26  { #ID, TYPE, ATTRS, nullptr, LANGS, nullptr },
27 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \
28  { #ID, TYPE, ATTRS, HEADER, LANGS, nullptr },
29 #include "clang/Basic/Builtins.def"
30 };
31 
32 const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
34  return BuiltinInfo[ID];
35  assert(((ID - Builtin::FirstTSBuiltin) <
36  (TSRecords.size() + AuxTSRecords.size())) &&
37  "Invalid builtin ID!");
38  if (isAuxBuiltinID(ID))
39  return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
40  return TSRecords[ID - Builtin::FirstTSBuiltin];
41 }
42 
44  const TargetInfo *AuxTarget) {
45  assert(TSRecords.empty() && "Already initialized target?");
46  TSRecords = Target.getTargetBuiltins();
47  if (AuxTarget)
48  AuxTSRecords = AuxTarget->getTargetBuiltins();
49 }
50 
51 bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) {
52  bool InStdNamespace = FuncName.consume_front("std-");
53  for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin;
54  ++i) {
55  if (FuncName.equals(BuiltinInfo[i].Name) &&
56  (bool)strchr(BuiltinInfo[i].Attributes, 'z') == InStdNamespace)
57  return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
58  }
59 
60  return false;
61 }
62 
63 /// Is this builtin supported according to the given language options?
65  const LangOptions &LangOpts) {
66  bool BuiltinsUnsupported =
67  LangOpts.NoBuiltin && strchr(BuiltinInfo.Attributes, 'f') != nullptr;
68  bool CorBuiltinsUnsupported =
69  !LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG);
70  bool MathBuiltinsUnsupported =
71  LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
72  llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
73  bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG);
74  bool MSModeUnsupported =
75  !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
76  bool ObjCUnsupported = !LangOpts.ObjC && BuiltinInfo.Langs == OBJC_LANG;
77  bool OclCUnsupported =
78  !LangOpts.OpenCL && (BuiltinInfo.Langs & ALL_OCL_LANGUAGES);
79  bool OclGASUnsupported =
80  !LangOpts.OpenCLGenericAddressSpace && (BuiltinInfo.Langs & OCL_GAS);
81  bool OclPipeUnsupported =
82  !LangOpts.OpenCLPipes && (BuiltinInfo.Langs & OCL_PIPE);
83  // Device side enqueue is not supported until OpenCL 2.0. In 2.0 and higher
84  // support is indicated with language option for blocks.
85  bool OclDSEUnsupported =
86  (LangOpts.getOpenCLCompatibleVersion() < 200 || !LangOpts.Blocks) &&
88  bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG;
89  bool CUDAUnsupported = !LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG;
90  bool CPlusPlusUnsupported =
91  !LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG;
92  return !BuiltinsUnsupported && !CorBuiltinsUnsupported &&
93  !MathBuiltinsUnsupported && !OclCUnsupported && !OclGASUnsupported &&
94  !OclPipeUnsupported && !OclDSEUnsupported && !OpenMPUnsupported &&
95  !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported &&
96  !CPlusPlusUnsupported && !CUDAUnsupported;
97 }
98 
99 /// initializeBuiltins - Mark the identifiers for all the builtins with their
100 /// appropriate builtin ID # and mark any non-portable builtin identifiers as
101 /// such.
103  const LangOptions& LangOpts) {
104  // Step #1: mark all target-independent builtins with their ID's.
105  for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
106  if (builtinIsSupported(BuiltinInfo[i], LangOpts)) {
107  Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
108  }
109 
110  // Step #2: Register target-specific builtins.
111  for (unsigned i = 0, e = TSRecords.size(); i != e; ++i)
112  if (builtinIsSupported(TSRecords[i], LangOpts))
113  Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);
114 
115  // Step #3: Register target-specific builtins for AuxTarget.
116  for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)
117  Table.get(AuxTSRecords[i].Name)
118  .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
119 
120  // Step #4: Unregister any builtins specified by -fno-builtin-foo.
121  for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
122  bool InStdNamespace = Name.consume_front("std-");
123  auto NameIt = Table.find(Name);
124  if (NameIt != Table.end()) {
125  unsigned ID = NameIt->second->getBuiltinID();
126  if (ID != Builtin::NotBuiltin && isPredefinedLibFunction(ID) &&
127  isInStdNamespace(ID) == InStdNamespace) {
128  Table.get(Name).setBuiltinID(Builtin::NotBuiltin);
129  }
130  }
131  }
132 }
133 
135  const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');
136  if (!WidthPos)
137  return 0;
138 
139  ++WidthPos;
140  assert(*WidthPos == ':' &&
141  "Vector width specifier must be followed by a ':'");
142  ++WidthPos;
143 
144  char *EndPos;
145  unsigned Width = ::strtol(WidthPos, &EndPos, 10);
146  assert(*EndPos == ':' && "Vector width specific must end with a ':'");
147  return Width;
148 }
149 
150 bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
151  bool &HasVAListArg, const char *Fmt) const {
152  assert(Fmt && "Not passed a format string");
153  assert(::strlen(Fmt) == 2 &&
154  "Format string needs to be two characters long");
155  assert(::toupper(Fmt[0]) == Fmt[1] &&
156  "Format string is not in the form \"xX\"");
157 
158  const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);
159  if (!Like)
160  return false;
161 
162  HasVAListArg = (*Like == Fmt[1]);
163 
164  ++Like;
165  assert(*Like == ':' && "Format specifier must be followed by a ':'");
166  ++Like;
167 
168  assert(::strchr(Like, ':') && "Format specifier must end with a ':'");
169  FormatIdx = ::strtol(Like, nullptr, 10);
170  return true;
171 }
172 
173 bool Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
174  bool &HasVAListArg) {
175  return isLike(ID, FormatIdx, HasVAListArg, "pP");
176 }
177 
178 bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
179  bool &HasVAListArg) {
180  return isLike(ID, FormatIdx, HasVAListArg, "sS");
181 }
182 
185  const char *CalleePos = ::strchr(getRecord(ID).Attributes, 'C');
186  if (!CalleePos)
187  return false;
188 
189  ++CalleePos;
190  assert(*CalleePos == '<' &&
191  "Callback callee specifier must be followed by a '<'");
192  ++CalleePos;
193 
194  char *EndPos;
195  int CalleeIdx = ::strtol(CalleePos, &EndPos, 10);
196  assert(CalleeIdx >= 0 && "Callee index is supposed to be positive!");
197  Encoding.push_back(CalleeIdx);
198 
199  while (*EndPos == ',') {
200  const char *PayloadPos = EndPos + 1;
201 
202  int PayloadIdx = ::strtol(PayloadPos, &EndPos, 10);
203  Encoding.push_back(PayloadIdx);
204  }
205 
206  assert(*EndPos == '>' && "Callback callee specifier must end with a '>'");
207  return true;
208 }
209 
210 bool Builtin::Context::canBeRedeclared(unsigned ID) const {
211  return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start ||
212  (!hasReferenceArgsOrResult(ID) && !hasCustomTypechecking(ID)) ||
213  isInStdNamespace(ID);
214 }
215 
217  StringRef RequiredFeatures, const llvm::StringMap<bool> &TargetFetureMap) {
218  // Return true if the builtin doesn't have any required features.
219  if (RequiredFeatures.empty())
220  return true;
221  assert(!RequiredFeatures.contains(' ') && "Space in feature list");
222 
223  TargetFeatures TF(TargetFetureMap);
224  return TF.hasRequiredFeatures(RequiredFeatures);
225 }
Builtins.h
clang::IdentifierTable::find
iterator find(StringRef Name) const
Definition: IdentifierTable.h:662
clang::Builtin::Context::isBuiltinFunc
static bool isBuiltinFunc(llvm::StringRef Name)
Returns true if this is a libc/libm function without the '__builtin_' prefix.
Definition: Builtins.cpp:51
clang::GNU_LANG
@ GNU_LANG
Definition: Builtins.h:33
clang::LangOptions::getOpenCLCompatibleVersion
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
Definition: LangOptions.cpp:55
clang::MS_LANG
@ MS_LANG
Definition: Builtins.h:37
clang::ALL_OCL_LANGUAGES
@ ALL_OCL_LANGUAGES
Definition: Builtins.h:44
clang::IdentifierTable::get
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Definition: IdentifierTable.h:596
builtinIsSupported
static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts)
Is this builtin supported according to the given language options?
Definition: Builtins.cpp:64
TargetInfo.h
clang::MultiVersionKind::Target
@ Target
clang::TargetInfo
Exposes information about the current target.
Definition: TargetInfo.h:189
clang::Builtin::Info::Langs
LanguageID Langs
Definition: Builtins.h:61
clang::CUDA_LANG
@ CUDA_LANG
Definition: Builtins.h:39
clang::Builtin::Info::Name
const char * Name
Definition: Builtins.h:60
clang::Builtin::TargetFeatures
TargetFeatures - This class is used to check whether the builtin function has the required tagert spe...
Definition: BuiltinTargetFeatures.h:32
BuiltinInfo
static const Builtin::Info BuiltinInfo[]
Definition: Builtins.cpp:21
clang::Builtin::Context::performsCallback
bool performsCallback(unsigned ID, llvm::SmallVectorImpl< int > &Encoding) const
Determine whether this builtin has callback behavior (see llvm::AbstractCallSites for details).
Definition: Builtins.cpp:183
clang::ALL_LANGUAGES
@ ALL_LANGUAGES
Definition: Builtins.h:46
clang::format::encoding::Encoding
Encoding
Definition: Encoding.h:27
LangOptions.h
clang::CXX_LANG
@ CXX_LANG
Definition: Builtins.h:35
IdentifierTable.h
clang::LangOptions::NoBuiltinFuncs
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
Definition: LangOptions.h:429
clang::TargetInfo::getTargetBuiltins
virtual ArrayRef< Builtin::Info > getTargetBuiltins() const =0
Return information about target-specific builtins for the current primary target, and info about whic...
clang::Builtin::Info::HeaderName
const char * HeaderName
Definition: Builtins.h:60
clang::OBJC_LANG
@ OBJC_LANG
Definition: Builtins.h:36
clang::Builtin::Context::getAuxBuiltinID
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition: Builtins.h:251
clang::Builtin::NotBuiltin
@ NotBuiltin
Definition: Builtins.h:53
clang::OCL_GAS
@ OCL_GAS
Definition: Builtins.h:41
clang::OCL_DSE
@ OCL_DSE
Definition: Builtins.h:43
clang::Builtin::evaluateRequiredTargetFeatures
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
clang::OCL_PIPE
@ OCL_PIPE
Definition: Builtins.h:42
clang::Builtin::Context::getRequiredVectorWidth
unsigned getRequiredVectorWidth(unsigned ID) const
Definition: Builtins.cpp:134
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:78
clang::OMP_LANG
@ OMP_LANG
Definition: Builtins.h:38
clang::Builtin::ID
ID
Definition: Builtins.h:52
clang
Definition: CalledOnceCheck.h:17
BuiltinTargetFeatures.h
clang::COR_LANG
@ COR_LANG
Definition: Builtins.h:40
clang::Builtin::Info
Definition: Builtins.h:59
clang::Builtin::Context::canBeRedeclared
bool canBeRedeclared(unsigned ID) const
Returns true if this is a builtin that can be redeclared.
Definition: Builtins.cpp:210
clang::IdentifierTable
Implements an efficient mapping from strings to IdentifierInfo nodes.
Definition: IdentifierTable.h:563
clang::IdentifierInfo::setBuiltinID
void setBuiltinID(unsigned ID)
Definition: IdentifierTable.h:308
clang::Builtin::FirstTSBuiltin
@ FirstTSBuiltin
Definition: Builtins.h:56
clang::Builtin::Context::isScanfLike
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:178
clang::IdentifierTable::end
iterator end() const
Definition: IdentifierTable.h:659
llvm::SmallVectorImpl
Definition: Randstruct.h:18
clang::Builtin::Context::isPrintfLike
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:173
clang::Builtin::Context::isAuxBuiltinID
bool isAuxBuiltinID(unsigned ID) const
Return true if builtin ID belongs to AuxTarget.
Definition: Builtins.h:245
clang::Builtin::Context::initializeBuiltins
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:102
clang::Builtin::Info::Attributes
const char * Attributes
Definition: Builtins.h:60
clang::Builtin::Context::InitializeTarget
void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget)
Perform target-specific initialization.
Definition: Builtins.cpp:43