@@ -29,54 +29,124 @@ const char *HeaderDesc::getName() const {
2929 llvm_unreachable (" Unknown HeaderDesc::HeaderID enum" );
3030}
3131
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
4137#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+ });
4349
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)) &&
4954 " 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 ();
5380}
5481
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+
55113void Builtin::Context::InitializeTarget (const TargetInfo &Target,
56114 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+ }
61125}
62126
63127bool Builtin::Context::isBuiltinFunc (llvm::StringRef FuncName) {
64128 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 ;
71138
72139 return false ;
73140}
74141
75142// / 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,
77145 const LangOptions &LangOpts) {
146+ auto AttributesStr = Strings[BuiltinInfo.Offsets .Attributes ];
147+
78148 /* Builtins Unsupported */
79- if (LangOpts.NoBuiltin && strchr (BuiltinInfo. Attributes , ' f' ) != nullptr )
149+ if (LangOpts.NoBuiltin && strchr (AttributesStr. data () , ' f' ) != nullptr )
80150 return false ;
81151 /* CorBuiltins Unsupported */
82152 if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG))
@@ -123,7 +193,7 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
123193 if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
124194 return false ;
125195 /* consteval Unsupported */
126- if (!LangOpts.CPlusPlus20 && strchr (BuiltinInfo. Attributes , ' G' ) != nullptr )
196+ if (!LangOpts.CPlusPlus20 && strchr (AttributesStr. data () , ' G' ) != nullptr )
127197 return false ;
128198 return true ;
129199}
@@ -132,22 +202,34 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
132202// / appropriate builtin ID # and mark any non-portable builtin identifiers as
133203// / such.
134204void 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+ }
146225
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+ }
151233
152234 // Step #4: Unregister any builtins specified by -fno-builtin-foo.
153235 for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs ) {
@@ -163,12 +245,8 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
163245 }
164246}
165247
166- std::string Builtin::Context::getQuotedName (unsigned ID) const {
167- return (llvm::Twine (" '" ) + getName (ID) + " '" ).str ();
168- }
169-
170248unsigned Builtin::Context::getRequiredVectorWidth (unsigned ID) const {
171- const char *WidthPos = ::strchr (getRecord (ID). Attributes , ' V' );
249+ const char *WidthPos = ::strchr (getAttributesString (ID), ' V' );
172250 if (!WidthPos)
173251 return 0 ;
174252
@@ -191,7 +269,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
191269 assert (::toupper (Fmt[0 ]) == Fmt[1 ] &&
192270 " Format string is not in the form \" xX\" " );
193271
194- const char *Like = ::strpbrk (getRecord (ID). Attributes , Fmt);
272+ const char *Like = ::strpbrk (getAttributesString (ID), Fmt);
195273 if (!Like)
196274 return false ;
197275
@@ -218,7 +296,7 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
218296
219297bool Builtin::Context::performsCallback (unsigned ID,
220298 SmallVectorImpl<int > &Encoding) const {
221- const char *CalleePos = ::strchr (getRecord (ID). Attributes , ' C' );
299+ const char *CalleePos = ::strchr (getAttributesString (ID), ' C' );
222300 if (!CalleePos)
223301 return false ;
224302
0 commit comments