@@ -55,7 +55,6 @@ struct HeaderDesc {
5555#undef HEADER
5656 } ID;
5757
58- constexpr HeaderDesc () : ID() {}
5958 constexpr HeaderDesc (HeaderID ID) : ID(ID) {}
6059
6160 const char *getName () const ;
@@ -69,152 +68,23 @@ enum ID {
6968 FirstTSBuiltin
7069};
7170
72- // The info used to represent each builtin.
7371struct Info {
74- // Rather than store pointers to the string literals describing these four
75- // aspects of builtins, we store offsets into a common string table.
76- struct StrOffsets {
77- int Name;
78- int Type;
79- int Attributes;
80- int Features;
81- } Offsets;
82-
72+ llvm::StringLiteral Name;
73+ const char *Type, *Attributes;
74+ const char *Features;
8375 HeaderDesc Header;
8476 LanguageID Langs;
8577};
8678
87- // The storage for `N` builtins. This contains a single pointer to the string
88- // table used for these builtins and an array of metadata for each builtin.
89- template <size_t N> struct Storage {
90- const char *StringTable;
91-
92- std::array<Info, N> Infos;
93-
94- // A constexpr function to construct the storage for a a given string table in
95- // the first argument and an array in the second argument. This is *only*
96- // expected to be used at compile time, we should mark it `consteval` when
97- // available.
98- //
99- // The `Infos` array is particularly special. This function expects an array
100- // of `Info` structs, where the string offsets of each entry refer to the
101- // *sizes* of those strings rather than their offsets, and for the target
102- // string to be in the provided string table at an offset the sum of all
103- // previous string sizes. This function walks the `Infos` array computing the
104- // running sum and replacing the sizes with the actual offsets in the string
105- // table that should be used. This arrangement is designed to make it easy to
106- // expand `.def` and `.inc` files with X-macros to construct both the string
107- // table and the `Info` structs in the arguments to this function.
108- static constexpr Storage<N> Make (const char *Strings,
109- std::array<Info, N> Infos) {
110- // Translate lengths to offsets.
111- int Offset = 0 ;
112- for (auto &I : Infos) {
113- Info::StrOffsets NewOffsets = {};
114- NewOffsets.Name = Offset;
115- Offset += I.Offsets .Name ;
116- NewOffsets.Type = Offset;
117- Offset += I.Offsets .Type ;
118- NewOffsets.Attributes = Offset;
119- Offset += I.Offsets .Attributes ;
120- NewOffsets.Features = Offset;
121- Offset += I.Offsets .Features ;
122- I.Offsets = NewOffsets;
123- }
124- return {Strings, Infos};
125- }
126- };
127-
128- // A detail macro used below to emit a string literal that, after string literal
129- // concatenation, ends up triggering the `-Woverlength-strings` warning. While
130- // the warning is useful in general to catch accidentally excessive strings,
131- // here we are creating them intentionally.
132- //
133- // This relies on a subtle aspect of `_Pragma`: that the *diagnostic* ones don't
134- // turn into actual tokens that would disrupt string literal concatenation.
135- #ifdef __clang__
136- #define CLANG_BUILTIN_DETAIL_STR_TABLE (S ) \
137- _Pragma (" clang diagnostic push" ) \
138- _Pragma(" clang diagnostic ignored \" -Woverlength-strings\" " ) \
139- S _Pragma(" clang diagnostic pop" )
140- #else
141- #define CLANG_BUILTIN_DETAIL_STR_TABLE (S ) S
142- #endif
143-
144- // A macro that can be used with `Builtins.def` and similar files as an X-macro
145- // to add the string arguments to a builtin string table. This is typically the
146- // target for the `BUILTIN`, `LANGBUILTIN`, or `LIBBUILTIN` macros in those
147- // files.
148- #define CLANG_BUILTIN_STR_TABLE (ID, TYPE, ATTRS ) \
149- CLANG_BUILTIN_DETAIL_STR_TABLE (#ID " \0 " TYPE " \0 " ATTRS " \0 " /* FEATURE*/ " \0 " )
150-
151- // A macro that can be used with target builtin `.def` and `.inc` files as an
152- // X-macro to add the string arguments to a builtin string table. this is
153- // typically the target for the `TARGET_BUILTIN` macro.
154- #define CLANG_TARGET_BUILTIN_STR_TABLE (ID, TYPE, ATTRS, FEATURE ) \
155- CLANG_BUILTIN_DETAIL_STR_TABLE (#ID " \0 " TYPE " \0 " ATTRS " \0 " FEATURE " \0 " )
156-
157- // A macro that can be used with target builtin `.def` and `.inc` files as an
158- // X-macro to add the string arguments to a builtin string table. this is
159- // typically the target for the `TARGET_HEADER_BUILTIN` macro. We can't delegate
160- // to `TARGET_BUILTIN` because the `FEATURE` string changes position.
161- #define CLANG_TARGET_HEADER_BUILTIN_STR_TABLE (ID, TYPE, ATTRS, HEADER, LANGS, \
162- FEATURE) \
163- CLANG_BUILTIN_DETAIL_STR_TABLE (#ID " \0 " TYPE " \0 " ATTRS " \0 " FEATURE " \0 " )
164-
165- // A detail macro used internally to compute the desired string table
166- // `StrOffsets` struct for arguments to `Storage::Make`.
167- #define CLANG_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS ) \
168- Builtin::Info::StrOffsets { \
169- sizeof (#ID), sizeof (TYPE), sizeof (ATTRS), sizeof (" " ) \
170- }
171-
172- // A detail macro used internally to compute the desired string table
173- // `StrOffsets` struct for arguments to `Storage::Make`.
174- #define CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS, FEATURE ) \
175- Builtin::Info::StrOffsets { \
176- sizeof (#ID), sizeof (TYPE), sizeof (ATTRS), sizeof (FEATURE) \
177- }
178-
179- // A set of macros that can be used with builtin `.def' files as an X-macro to
180- // create an `Info` struct for a particular builtin. It both computes the
181- // `StrOffsets` value for the string table (the lengths here, translated to
182- // offsets by the Storage::Make function), and the other metadata for each
183- // builtin.
184- //
185- // There is a corresponding macro for each of `BUILTIN`, `LANGBUILTIN`,
186- // `LIBBUILTIN`, `TARGET_BUILTIN`, and `TARGET_HEADER_BUILTIN`.
187- #define CLANG_BUILTIN_ENTRY (ID, TYPE, ATTRS ) \
188- Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS), \
189- HeaderDesc::NO_HEADER, ALL_LANGUAGES},
190- #define CLANG_LANGBUILTIN_ENTRY (ID, TYPE, ATTRS, LANG ) \
191- Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS), \
192- HeaderDesc::NO_HEADER, LANG},
193- #define CLANG_LIBBUILTIN_ENTRY (ID, TYPE, ATTRS, HEADER, LANG ) \
194- Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS), \
195- HeaderDesc::HEADER, LANG},
196- #define CLANG_TARGET_BUILTIN_ENTRY (ID, TYPE, ATTRS, FEATURE ) \
197- Builtin::Info{ \
198- CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS, FEATURE), \
199- HeaderDesc::NO_HEADER, ALL_LANGUAGES},
200- #define CLANG_TARGET_HEADER_BUILTIN_ENTRY (ID, TYPE, ATTRS, HEADER, LANG, \
201- FEATURE) \
202- Builtin::Info{ \
203- CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS (ID, TYPE, ATTRS, FEATURE), \
204- HeaderDesc::HEADER, LANG},
205-
20679// / Holds information about both target-independent and
20780// / target-specific builtins, allowing easy queries by clients.
20881// /
20982// / Builtins from an optional auxiliary target are stored in
21083// / AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
21184// / be translated back with getAuxBuiltinID() before use.
21285class Context {
213- const char *TSStrTable = nullptr ;
214- const char *AuxTSStrTable = nullptr ;
215-
216- llvm::ArrayRef<Info> TSInfos;
217- llvm::ArrayRef<Info> AuxTSInfos;
86+ llvm::ArrayRef<Info> TSRecords;
87+ llvm::ArrayRef<Info> AuxTSRecords;
21888
21989public:
22090 Context () = default ;
@@ -230,13 +100,12 @@ class Context {
230100
231101 // / Return the identifier name for the specified builtin,
232102 // / e.g. "__builtin_abs".
233- llvm::StringRef getName (unsigned ID) const ;
103+ llvm::StringRef getName (unsigned ID) const { return getRecord (ID). Name ; }
234104
235105 // / Get the type descriptor string for the specified builtin.
236- const char *getTypeString (unsigned ID) const ;
237-
238- // / Get the attributes descriptor string for the specified builtin.
239- const char *getAttributesString (unsigned ID) const ;
106+ const char *getTypeString (unsigned ID) const {
107+ return getRecord (ID).Type ;
108+ }
240109
241110 // / Return true if this function is a target-specific builtin.
242111 bool isTSBuiltin (unsigned ID) const {
@@ -245,40 +114,40 @@ class Context {
245114
246115 // / Return true if this function has no side effects.
247116 bool isPure (unsigned ID) const {
248- return strchr (getAttributesString (ID), ' U' ) != nullptr ;
117+ return strchr (getRecord (ID). Attributes , ' U' ) != nullptr ;
249118 }
250119
251120 // / Return true if this function has no side effects and doesn't
252121 // / read memory.
253122 bool isConst (unsigned ID) const {
254- return strchr (getAttributesString (ID), ' c' ) != nullptr ;
123+ return strchr (getRecord (ID). Attributes , ' c' ) != nullptr ;
255124 }
256125
257126 // / Return true if we know this builtin never throws an exception.
258127 bool isNoThrow (unsigned ID) const {
259- return strchr (getAttributesString (ID), ' n' ) != nullptr ;
128+ return strchr (getRecord (ID). Attributes , ' n' ) != nullptr ;
260129 }
261130
262131 // / Return true if we know this builtin never returns.
263132 bool isNoReturn (unsigned ID) const {
264- return strchr (getAttributesString (ID), ' r' ) != nullptr ;
133+ return strchr (getRecord (ID). Attributes , ' r' ) != nullptr ;
265134 }
266135
267136 // / Return true if we know this builtin can return twice.
268137 bool isReturnsTwice (unsigned ID) const {
269- return strchr (getAttributesString (ID), ' j' ) != nullptr ;
138+ return strchr (getRecord (ID). Attributes , ' j' ) != nullptr ;
270139 }
271140
272141 // / Returns true if this builtin does not perform the side-effects
273142 // / of its arguments.
274143 bool isUnevaluated (unsigned ID) const {
275- return strchr (getAttributesString (ID), ' u' ) != nullptr ;
144+ return strchr (getRecord (ID). Attributes , ' u' ) != nullptr ;
276145 }
277146
278147 // / Return true if this is a builtin for a libc/libm function,
279148 // / with a "__builtin_" prefix (e.g. __builtin_abs).
280149 bool isLibFunction (unsigned ID) const {
281- return strchr (getAttributesString (ID), ' F' ) != nullptr ;
150+ return strchr (getRecord (ID). Attributes , ' F' ) != nullptr ;
282151 }
283152
284153 // / Determines whether this builtin is a predefined libc/libm
@@ -289,29 +158,29 @@ class Context {
289158 // / they do not, but they are recognized as builtins once we see
290159 // / a declaration.
291160 bool isPredefinedLibFunction (unsigned ID) const {
292- return strchr (getAttributesString (ID), ' f' ) != nullptr ;
161+ return strchr (getRecord (ID). Attributes , ' f' ) != nullptr ;
293162 }
294163
295164 // / Returns true if this builtin requires appropriate header in other
296165 // / compilers. In Clang it will work even without including it, but we can emit
297166 // / a warning about missing header.
298167 bool isHeaderDependentFunction (unsigned ID) const {
299- return strchr (getAttributesString (ID), ' h' ) != nullptr ;
168+ return strchr (getRecord (ID). Attributes , ' h' ) != nullptr ;
300169 }
301170
302171 // / Determines whether this builtin is a predefined compiler-rt/libgcc
303172 // / function, such as "__clear_cache", where we know the signature a
304173 // / priori.
305174 bool isPredefinedRuntimeFunction (unsigned ID) const {
306- return strchr (getAttributesString (ID), ' i' ) != nullptr ;
175+ return strchr (getRecord (ID). Attributes , ' i' ) != nullptr ;
307176 }
308177
309178 // / Determines whether this builtin is a C++ standard library function
310179 // / that lives in (possibly-versioned) namespace std, possibly a template
311180 // / specialization, where the signature is determined by the standard library
312181 // / declaration.
313182 bool isInStdNamespace (unsigned ID) const {
314- return strchr (getAttributesString (ID), ' z' ) != nullptr ;
183+ return strchr (getRecord (ID). Attributes , ' z' ) != nullptr ;
315184 }
316185
317186 // / Determines whether this builtin can have its address taken with no
@@ -325,33 +194,33 @@ class Context {
325194
326195 // / Determines whether this builtin has custom typechecking.
327196 bool hasCustomTypechecking (unsigned ID) const {
328- return strchr (getAttributesString (ID), ' t' ) != nullptr ;
197+ return strchr (getRecord (ID). Attributes , ' t' ) != nullptr ;
329198 }
330199
331200 // / Determines whether a declaration of this builtin should be recognized
332201 // / even if the type doesn't match the specified signature.
333202 bool allowTypeMismatch (unsigned ID) const {
334- return strchr (getAttributesString (ID), ' T' ) != nullptr ||
203+ return strchr (getRecord (ID). Attributes , ' T' ) != nullptr ||
335204 hasCustomTypechecking (ID);
336205 }
337206
338207 // / Determines whether this builtin has a result or any arguments which
339208 // / are pointer types.
340209 bool hasPtrArgsOrResult (unsigned ID) const {
341- return strchr (getTypeString (ID), ' *' ) != nullptr ;
210+ return strchr (getRecord (ID). Type , ' *' ) != nullptr ;
342211 }
343212
344213 // / Return true if this builtin has a result or any arguments which are
345214 // / reference types.
346215 bool hasReferenceArgsOrResult (unsigned ID) const {
347- return strchr (getTypeString (ID), ' &' ) != nullptr ||
348- strchr (getTypeString (ID), ' A' ) != nullptr ;
216+ return strchr (getRecord (ID). Type , ' &' ) != nullptr ||
217+ strchr (getRecord (ID). Type , ' A' ) != nullptr ;
349218 }
350219
351220 // / If this is a library function that comes from a specific
352221 // / header, retrieve that header name.
353222 const char *getHeaderName (unsigned ID) const {
354- return getInfo (ID).Header .getName ();
223+ return getRecord (ID).Header .getName ();
355224 }
356225
357226 // / Determine whether this builtin is like printf in its
@@ -376,25 +245,27 @@ class Context {
376245 // / Such functions can be const when the MathErrno lang option and FP
377246 // / exceptions are disabled.
378247 bool isConstWithoutErrnoAndExceptions (unsigned ID) const {
379- return strchr (getAttributesString (ID), ' e' ) != nullptr ;
248+ return strchr (getRecord (ID). Attributes , ' e' ) != nullptr ;
380249 }
381250
382251 bool isConstWithoutExceptions (unsigned ID) const {
383- return strchr (getAttributesString (ID), ' g' ) != nullptr ;
252+ return strchr (getRecord (ID). Attributes , ' g' ) != nullptr ;
384253 }
385254
386- const char *getRequiredFeatures (unsigned ID) const ;
255+ const char *getRequiredFeatures (unsigned ID) const {
256+ return getRecord (ID).Features ;
257+ }
387258
388259 unsigned getRequiredVectorWidth (unsigned ID) const ;
389260
390261 // / Return true if builtin ID belongs to AuxTarget.
391262 bool isAuxBuiltinID (unsigned ID) const {
392- return ID >= (Builtin::FirstTSBuiltin + TSInfos .size ());
263+ return ID >= (Builtin::FirstTSBuiltin + TSRecords .size ());
393264 }
394265
395266 // / Return real builtin ID (i.e. ID it would have during compilation
396267 // / for AuxTarget).
397- unsigned getAuxBuiltinID (unsigned ID) const { return ID - TSInfos .size (); }
268+ unsigned getAuxBuiltinID (unsigned ID) const { return ID - TSRecords .size (); }
398269
399270 // / Returns true if this is a libc/libm function without the '__builtin_'
400271 // / prefix.
@@ -406,20 +277,16 @@ class Context {
406277
407278 // / Return true if this function can be constant evaluated by Clang frontend.
408279 bool isConstantEvaluated (unsigned ID) const {
409- return strchr (getAttributesString (ID), ' E' ) != nullptr ;
280+ return strchr (getRecord (ID). Attributes , ' E' ) != nullptr ;
410281 }
411282
412283 // / Returns true if this is an immediate (consteval) function
413284 bool isImmediate (unsigned ID) const {
414- return strchr (getAttributesString (ID), ' G' ) != nullptr ;
285+ return strchr (getRecord (ID). Attributes , ' G' ) != nullptr ;
415286 }
416287
417288private:
418- std::pair<const char *, const Info &> getStrTableAndInfo (unsigned ID) const ;
419-
420- const Info &getInfo (unsigned ID) const {
421- return getStrTableAndInfo (ID).second ;
422- }
289+ const Info &getRecord (unsigned ID) const ;
423290
424291 // / Helper function for isPrintfLike and isScanfLike.
425292 bool isLike (unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
0 commit comments