@@ -29,54 +29,124 @@ const char *HeaderDesc::getName() const {
29
29
llvm_unreachable (" Unknown HeaderDesc::HeaderID enum" );
30
30
}
31
31
32
- static constexpr Builtin::Info BuiltinInfo[] = {
33
- {" not a builtin function" , nullptr , nullptr , nullptr , HeaderDesc::NO_HEADER,
34
- ALL_LANGUAGES},
35
- #define BUILTIN (ID, TYPE, ATTRS ) \
36
- {#ID, TYPE, ATTRS, nullptr , HeaderDesc::NO_HEADER, ALL_LANGUAGES},
37
- #define LANGBUILTIN (ID, TYPE, ATTRS, LANGS ) \
38
- {#ID, TYPE, ATTRS, nullptr , HeaderDesc::NO_HEADER, LANGS},
39
- #define LIBBUILTIN (ID, TYPE, ATTRS, HEADER, LANGS ) \
40
- {#ID, TYPE, ATTRS, nullptr , HeaderDesc::HEADER, LANGS},
32
+ static constexpr llvm::StringTable BuiltinStrings =
33
+ CLANG_BUILTIN_STR_TABLE_START
34
+ // We inject a non-builtin string into the table.
35
+ CLANG_BUILTIN_STR_TABLE (" not a builtin function" , " " , " " )
36
+ #define BUILTIN CLANG_BUILTIN_STR_TABLE
41
37
#include " clang/Basic/Builtins.inc"
42
- };
38
+ ;
39
+ static_assert (BuiltinStrings.size() < 100'000);
40
+
41
+ static constexpr auto BuiltinInfos =
42
+ Builtin::MakeInfos<Builtin::FirstTSBuiltin>(
43
+ {CLANG_BUILTIN_ENTRY (" not a builtin function" , " " , " " )
44
+ #define BUILTIN CLANG_BUILTIN_ENTRY
45
+ #define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY
46
+ #define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
47
+ #include " clang/Basic/Builtins.inc"
48
+ });
43
49
44
- const Builtin::Info &Builtin::Context::getRecord (unsigned ID) const {
45
- if (ID < Builtin::FirstTSBuiltin)
46
- return BuiltinInfo[ID];
47
- assert (((ID - Builtin::FirstTSBuiltin) <
48
- (TSRecords.size () + AuxTSRecords.size ())) &&
50
+ std::pair<const Builtin::InfosShard &, const Builtin::Info &>
51
+ Builtin::Context::getShardAndInfo (unsigned ID) const {
52
+ assert ((ID < (Builtin::FirstTSBuiltin + NumTargetBuiltins +
53
+ NumAuxTargetBuiltins)) &&
49
54
" Invalid builtin ID!" );
50
- if (isAuxBuiltinID (ID))
51
- return AuxTSRecords[getAuxBuiltinID (ID) - Builtin::FirstTSBuiltin];
52
- return TSRecords[ID - Builtin::FirstTSBuiltin];
55
+
56
+ ArrayRef<InfosShard> Shards = BuiltinShards;
57
+ if (isAuxBuiltinID (ID)) {
58
+ Shards = AuxTargetShards;
59
+ ID = getAuxBuiltinID (ID) - Builtin::FirstTSBuiltin;
60
+ } else if (ID >= Builtin::FirstTSBuiltin) {
61
+ Shards = TargetShards;
62
+ ID -= Builtin::FirstTSBuiltin;
63
+ }
64
+
65
+ // Loop over the shards to find the one matching this ID. We don't expect to
66
+ // have many shards and so its better to search linearly than with a binary
67
+ // search.
68
+ for (const auto &Shard : Shards) {
69
+ if (ID < Shard.Infos .size ()) {
70
+ return {Shard, Shard.Infos [ID]};
71
+ }
72
+
73
+ ID -= Shard.Infos .size ();
74
+ }
75
+ llvm_unreachable (" Invalid target builtin shard structure!" );
76
+ }
77
+
78
+ std::string Builtin::Info::getName (const Builtin::InfosShard &Shard) const {
79
+ return (Twine (Shard.NamePrefix ) + (*Shard.Strings )[Offsets.Name ]).str ();
53
80
}
54
81
82
+ // / Return the identifier name for the specified builtin,
83
+ // / e.g. "__builtin_abs".
84
+ std::string Builtin::Context::getName (unsigned ID) const {
85
+ const auto &[Shard, I] = getShardAndInfo (ID);
86
+ return I.getName (Shard);
87
+ }
88
+
89
+ std::string Builtin::Context::getQuotedName (unsigned ID) const {
90
+ const auto &[Shard, I] = getShardAndInfo (ID);
91
+ return (Twine (" '" ) + Shard.NamePrefix + (*Shard.Strings )[I.Offsets .Name ] +
92
+ " '" )
93
+ .str ();
94
+ }
95
+
96
+ const char *Builtin::Context::getTypeString (unsigned ID) const {
97
+ const auto &[Shard, I] = getShardAndInfo (ID);
98
+ return (*Shard.Strings )[I.Offsets .Type ].data ();
99
+ }
100
+
101
+ const char *Builtin::Context::getAttributesString (unsigned ID) const {
102
+ const auto &[Shard, I] = getShardAndInfo (ID);
103
+ return (*Shard.Strings )[I.Offsets .Attributes ].data ();
104
+ }
105
+
106
+ const char *Builtin::Context::getRequiredFeatures (unsigned ID) const {
107
+ const auto &[Shard, I] = getShardAndInfo (ID);
108
+ return (*Shard.Strings )[I.Offsets .Features ].data ();
109
+ }
110
+
111
+ Builtin::Context::Context () : BuiltinShards{{&BuiltinStrings, BuiltinInfos}} {}
112
+
55
113
void Builtin::Context::InitializeTarget (const TargetInfo &Target,
56
114
const TargetInfo *AuxTarget) {
57
- assert (TSRecords.empty () && " Already initialized target?" );
58
- TSRecords = Target.getTargetBuiltins ();
59
- if (AuxTarget)
60
- AuxTSRecords = AuxTarget->getTargetBuiltins ();
115
+ assert (TargetShards.empty () && " Already initialized target?" );
116
+ assert (NumTargetBuiltins == 0 && " Already initialized target?" );
117
+ TargetShards = Target.getTargetBuiltins ();
118
+ for (const auto &Shard : TargetShards)
119
+ NumTargetBuiltins += Shard.Infos .size ();
120
+ if (AuxTarget) {
121
+ AuxTargetShards = AuxTarget->getTargetBuiltins ();
122
+ for (const auto &Shard : AuxTargetShards)
123
+ NumAuxTargetBuiltins += Shard.Infos .size ();
124
+ }
61
125
}
62
126
63
127
bool Builtin::Context::isBuiltinFunc (llvm::StringRef FuncName) {
64
128
bool InStdNamespace = FuncName.consume_front (" std-" );
65
- for (unsigned i = Builtin::NotBuiltin + 1 ; i != Builtin::FirstTSBuiltin;
66
- ++i) {
67
- if (FuncName == BuiltinInfo[i].Name &&
68
- (bool )strchr (BuiltinInfo[i].Attributes , ' z' ) == InStdNamespace)
69
- return strchr (BuiltinInfo[i].Attributes , ' f' ) != nullptr ;
70
- }
129
+ for (const auto &Shard : {InfosShard{&BuiltinStrings, BuiltinInfos}})
130
+ if (llvm::StringRef FuncNameSuffix = FuncName;
131
+ FuncNameSuffix.consume_front (Shard.NamePrefix ))
132
+ for (const auto &I : Shard.Infos )
133
+ if (FuncNameSuffix == (*Shard.Strings )[I.Offsets .Name ] &&
134
+ (bool )strchr ((*Shard.Strings )[I.Offsets .Attributes ].data (), ' z' ) ==
135
+ InStdNamespace)
136
+ return strchr ((*Shard.Strings )[I.Offsets .Attributes ].data (), ' f' ) !=
137
+ nullptr ;
71
138
72
139
return false ;
73
140
}
74
141
75
142
// / Is this builtin supported according to the given language options?
76
- static bool builtinIsSupported (const Builtin::Info &BuiltinInfo,
143
+ static bool builtinIsSupported (const llvm::StringTable &Strings,
144
+ const Builtin::Info &BuiltinInfo,
77
145
const LangOptions &LangOpts) {
146
+ auto AttributesStr = Strings[BuiltinInfo.Offsets .Attributes ];
147
+
78
148
/* Builtins Unsupported */
79
- if (LangOpts.NoBuiltin && strchr (BuiltinInfo. Attributes , ' f' ) != nullptr )
149
+ if (LangOpts.NoBuiltin && strchr (AttributesStr. data () , ' f' ) != nullptr )
80
150
return false ;
81
151
/* CorBuiltins Unsupported */
82
152
if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG))
@@ -123,7 +193,7 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
123
193
if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
124
194
return false ;
125
195
/* consteval Unsupported */
126
- if (!LangOpts.CPlusPlus20 && strchr (BuiltinInfo. Attributes , ' G' ) != nullptr )
196
+ if (!LangOpts.CPlusPlus20 && strchr (AttributesStr. data () , ' G' ) != nullptr )
127
197
return false ;
128
198
return true ;
129
199
}
@@ -132,22 +202,34 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
132
202
// / appropriate builtin ID # and mark any non-portable builtin identifiers as
133
203
// / such.
134
204
void Builtin::Context::initializeBuiltins (IdentifierTable &Table,
135
- const LangOptions& LangOpts) {
136
- // Step #1: mark all target-independent builtins with their ID's.
137
- for (unsigned i = Builtin::NotBuiltin + 1 ; i != Builtin::FirstTSBuiltin; ++i)
138
- if (builtinIsSupported (BuiltinInfo[i], LangOpts)) {
139
- Table.get (BuiltinInfo[i].Name ).setBuiltinID (i);
140
- }
141
-
142
- // Step #2: Register target-specific builtins.
143
- for (unsigned i = 0 , e = TSRecords.size (); i != e; ++i)
144
- if (builtinIsSupported (TSRecords[i], LangOpts))
145
- Table.get (TSRecords[i].Name ).setBuiltinID (i + Builtin::FirstTSBuiltin);
205
+ const LangOptions &LangOpts) {
206
+ {
207
+ unsigned ID = 0 ;
208
+ // Step #1: mark all target-independent builtins with their ID's.
209
+ for (const auto &Shard : BuiltinShards)
210
+ for (const auto &I : Shard.Infos ) {
211
+ // If this is a real builtin (ID != 0) and is supported, add it.
212
+ if (ID != 0 && builtinIsSupported (*Shard.Strings , I, LangOpts))
213
+ Table.get (I.getName (Shard)).setBuiltinID (ID);
214
+ ++ID;
215
+ }
216
+ assert (ID == FirstTSBuiltin && " Should have added all non-target IDs!" );
217
+
218
+ // Step #2: Register target-specific builtins.
219
+ for (const auto &Shard : TargetShards)
220
+ for (const auto &I : Shard.Infos ) {
221
+ if (builtinIsSupported (*Shard.Strings , I, LangOpts))
222
+ Table.get (I.getName (Shard)).setBuiltinID (ID);
223
+ ++ID;
224
+ }
146
225
147
- // Step #3: Register target-specific builtins for AuxTarget.
148
- for (unsigned i = 0 , e = AuxTSRecords.size (); i != e; ++i)
149
- Table.get (AuxTSRecords[i].Name )
150
- .setBuiltinID (i + Builtin::FirstTSBuiltin + TSRecords.size ());
226
+ // Step #3: Register target-specific builtins for AuxTarget.
227
+ for (const auto &Shard : AuxTargetShards)
228
+ for (const auto &I : Shard.Infos ) {
229
+ Table.get (I.getName (Shard)).setBuiltinID (ID);
230
+ ++ID;
231
+ }
232
+ }
151
233
152
234
// Step #4: Unregister any builtins specified by -fno-builtin-foo.
153
235
for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs ) {
@@ -163,12 +245,8 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
163
245
}
164
246
}
165
247
166
- std::string Builtin::Context::getQuotedName (unsigned ID) const {
167
- return (llvm::Twine (" '" ) + getName (ID) + " '" ).str ();
168
- }
169
-
170
248
unsigned Builtin::Context::getRequiredVectorWidth (unsigned ID) const {
171
- const char *WidthPos = ::strchr (getRecord (ID). Attributes , ' V' );
249
+ const char *WidthPos = ::strchr (getAttributesString (ID), ' V' );
172
250
if (!WidthPos)
173
251
return 0 ;
174
252
@@ -191,7 +269,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
191
269
assert (::toupper (Fmt[0 ]) == Fmt[1 ] &&
192
270
" Format string is not in the form \" xX\" " );
193
271
194
- const char *Like = ::strpbrk (getRecord (ID). Attributes , Fmt);
272
+ const char *Like = ::strpbrk (getAttributesString (ID), Fmt);
195
273
if (!Like)
196
274
return false ;
197
275
@@ -218,7 +296,7 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
218
296
219
297
bool Builtin::Context::performsCallback (unsigned ID,
220
298
SmallVectorImpl<int > &Encoding) const {
221
- const char *CalleePos = ::strchr (getRecord (ID). Attributes , ' C' );
299
+ const char *CalleePos = ::strchr (getAttributesString (ID), ' C' );
222
300
if (!CalleePos)
223
301
return false ;
224
302
0 commit comments