Skip to content

Commit 67f07fe

Browse files
chandlercnikic
authored andcommitted
Switch builtin strings to use string tables
The Clang binary (and any binary linking Clang as a library), when built using PIE, ends up with a pretty shocking number of dynamic relocations to apply to the executable image: roughly 400k. Each of these takes up binary space in the executable, and perhaps most interestingly takes start-up time to apply the relocations. The largest pattern I identified were the strings used to describe target builtins. The addresses of these string literals were stored into huge arrays, each one requiring a dynamic relocation. The way to avoid this is to design the target builtins to use a single large table of strings and offsets within the table for the individual strings. This switches the builtin management to such a scheme. This saves over 100k dynamic relocations by my measurement, an over 25% reduction. Just looking at byte size improvements, using the `bloaty` tool to compare a newly built `clang` binary to an old one: ``` FILE SIZE VM SIZE -------------- -------------- +1.4% +653Ki +1.4% +653Ki .rodata +0.0% +960 +0.0% +960 .text +0.0% +197 +0.0% +197 .dynstr +0.0% +184 +0.0% +184 .eh_frame +0.0% +96 +0.0% +96 .dynsym +0.0% +40 +0.0% +40 .eh_frame_hdr +114% +32 [ = ] 0 [Unmapped] +0.0% +20 +0.0% +20 .gnu.hash +0.0% +8 +0.0% +8 .gnu.version +0.9% +7 +0.9% +7 [LOAD rust-lang#2 [R]] [ = ] 0 -75.4% -3.00Ki .relro_padding -16.1% -802Ki -16.1% -802Ki .data.rel.ro -27.3% -2.52Mi -27.3% -2.52Mi .rela.dyn -1.6% -2.66Mi -1.6% -2.66Mi TOTAL ``` We get a 16% reduction in the `.data.rel.ro` section, and nearly 30% reduction in `.rela.dyn` where those reloctaions are stored. This is also visible in my benchmarking of binary start-up overhead at least: ``` Benchmark 1: ./old_clang --version Time (mean ± σ): 17.6 ms ± 1.5 ms [User: 4.1 ms, System: 13.3 ms] Range (min … max): 14.2 ms … 22.8 ms 162 runs Benchmark 2: ./new_clang --version Time (mean ± σ): 15.5 ms ± 1.4 ms [User: 3.6 ms, System: 11.8 ms] Range (min … max): 12.4 ms … 20.3 ms 216 runs Summary './new_clang --version' ran 1.13 ± 0.14 times faster than './old_clang --version' ``` We get about 2ms faster `--version` runs. While there is a lot of noise in binary execution time, this delta is pretty consistent, and represents over 10% improvement. This is particularly interesting to me because for very short source files, repeatedly starting the `clang` binary is actually the dominant cost. For example, `configure` scripts running against the `clang` compiler are slow in large part because of binary start up time, not the time to process the actual inputs to the compiler. ---- This PR implements the string tables using `constexpr` code and the existing macro system. I understand that the builtins are moving towards a TableGen model, and if complete that would provide more options for modeling this. Unfortunately, that migration isn't complete, and even the parts that are migrated still rely on the ability to break out of the TableGen model and directly expand an X-macro style `BUILTIN(...)` textually. I looked at trying to complete the move to TableGen, but it would both require the difficult migration of the remaining targets, and solving some tricky problems with how to move away from any macro-based expansion. I was also able to find a reasonably clean and effective way of doing this with the existing macros and some `constexpr` code that I think is clean enough to be a pretty good intermediate state, and maybe give a good target for the eventual TableGen solution. I was also able to factor the macros into set of consistent patterns that avoids a significant regression in overall boilerplate. There is one challenge with this approach: it requires the host compiler to support (very) long string literals, a bit over half a meg. =/ The current minimum MSVC version rejects these, but the very next patch release (16.8) removed that restriction. I'm going to send out a separate PR / RFC to raise the minimum version by one patch release, which I hope is acceptable as the current version was set years ago. FWIW, there are a few more low-hanging fruit sources of excessive dynamic relocations, maybe as many as 50k to 100k more that I'll take a look at to see if I can identify easy fixes. Beyond that, it seems to get quite difficult. It might be worth adding some guidance to developer documentation to try to avoid creating global data structures that _repeatedly_ store pointers to other globals. Fix from code review switch back to clang-specific warning suppression review feedback format
1 parent eeadd01 commit 67f07fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+610
-309
lines changed

clang/include/clang/Basic/Builtins.h

+173-36
Large diffs are not rendered by default.

clang/include/clang/Basic/BuiltinsPPC.def

+1
Original file line numberDiff line numberDiff line change
@@ -1138,5 +1138,6 @@ UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true,
11381138
// FIXME: Obviously incomplete.
11391139

11401140
#undef BUILTIN
1141+
#undef TARGET_BUILTIN
11411142
#undef CUSTOM_BUILTIN
11421143
#undef UNALIASED_CUSTOM_BUILTIN

clang/include/clang/Basic/TargetInfo.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "clang/Basic/AddressSpaces.h"
1818
#include "clang/Basic/BitmaskEnum.h"
19+
#include "clang/Basic/Builtins.h"
1920
#include "clang/Basic/CFProtectionOptions.h"
2021
#include "clang/Basic/CodeGenOptions.h"
2122
#include "clang/Basic/LLVM.h"
@@ -1009,11 +1010,11 @@ class TargetInfo : public TransferrableTargetInfo,
10091010
virtual void getTargetDefines(const LangOptions &Opts,
10101011
MacroBuilder &Builder) const = 0;
10111012

1012-
1013-
/// Return information about target-specific builtins for
1014-
/// the current primary target, and info about which builtins are non-portable
1015-
/// across the current set of primary and secondary targets.
1016-
virtual ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;
1013+
/// Return information about target-specific builtins for the current primary
1014+
/// target, and info about which builtins are non-portable across the current
1015+
/// set of primary and secondary targets.
1016+
virtual std::pair<const char *, ArrayRef<Builtin::Info>>
1017+
getTargetBuiltinStorage() const = 0;
10171018

10181019
/// Returns target-specific min and max values VScale_Range.
10191020
virtual std::optional<std::pair<unsigned, unsigned>>

clang/lib/Basic/Builtins.cpp

+81-39
Original file line numberDiff line numberDiff line change
@@ -29,54 +29,93 @@ 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 auto BuiltinStorage =
33+
Builtin::Storage<Builtin::FirstTSBuiltin>::Make(
34+
CLANG_BUILTIN_STR_TABLE("not a builtin function", "", "")
35+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
4136
#include "clang/Basic/Builtins.inc"
42-
};
37+
,
38+
{CLANG_BUILTIN_ENTRY("not a builtin function", "", "")
39+
#define BUILTIN CLANG_BUILTIN_ENTRY
40+
#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY
41+
#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
42+
#include "clang/Basic/Builtins.inc"
43+
});
4344

44-
const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
45+
std::pair<const char *, const Builtin::Info &>
46+
Builtin::Context::getStrTableAndInfo(unsigned ID) const {
4547
if (ID < Builtin::FirstTSBuiltin)
46-
return BuiltinInfo[ID];
47-
assert(((ID - Builtin::FirstTSBuiltin) <
48-
(TSRecords.size() + AuxTSRecords.size())) &&
49-
"Invalid builtin ID!");
48+
return {BuiltinStorage.StringTable, BuiltinStorage.Infos[ID]};
49+
assert(
50+
((ID - Builtin::FirstTSBuiltin) < (TSInfos.size() + AuxTSInfos.size())) &&
51+
"Invalid builtin ID!");
5052
if (isAuxBuiltinID(ID))
51-
return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
52-
return TSRecords[ID - Builtin::FirstTSBuiltin];
53+
return {AuxTSStrTable,
54+
AuxTSInfos[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin]};
55+
return {TSStrTable, TSInfos[ID - Builtin::FirstTSBuiltin]};
56+
}
57+
58+
static llvm::StringRef getStrFromTable(const char *StrTable, int Offset) {
59+
return &StrTable[Offset];
60+
}
61+
62+
/// Return the identifier name for the specified builtin,
63+
/// e.g. "__builtin_abs".
64+
llvm::StringRef Builtin::Context::getName(unsigned ID) const {
65+
const auto &[StrTable, I] = getStrTableAndInfo(ID);
66+
return getStrFromTable(StrTable, I.Offsets.Name);
67+
}
68+
69+
const char *Builtin::Context::getTypeString(unsigned ID) const {
70+
const auto &[StrTable, I] = getStrTableAndInfo(ID);
71+
return getStrFromTable(StrTable, I.Offsets.Type).data();
72+
}
73+
74+
const char *Builtin::Context::getAttributesString(unsigned ID) const {
75+
const auto &[StrTable, I] = getStrTableAndInfo(ID);
76+
return getStrFromTable(StrTable, I.Offsets.Attributes).data();
77+
}
78+
79+
const char *Builtin::Context::getRequiredFeatures(unsigned ID) const {
80+
const auto &[StrTable, I] = getStrTableAndInfo(ID);
81+
return getStrFromTable(StrTable, I.Offsets.Features).data();
5382
}
5483

5584
void Builtin::Context::InitializeTarget(const TargetInfo &Target,
5685
const TargetInfo *AuxTarget) {
57-
assert(TSRecords.empty() && "Already initialized target?");
58-
TSRecords = Target.getTargetBuiltins();
59-
if (AuxTarget)
60-
AuxTSRecords = AuxTarget->getTargetBuiltins();
86+
assert(TSStrTable == nullptr && "Already initialized target?");
87+
assert(TSInfos.empty() && "Already initialized target?");
88+
std::tie(TSStrTable, TSInfos) = Target.getTargetBuiltinStorage();
89+
if (AuxTarget) {
90+
std::tie(AuxTSStrTable, AuxTSInfos) = AuxTarget->getTargetBuiltinStorage();
91+
}
6192
}
6293

6394
bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) {
6495
bool InStdNamespace = FuncName.consume_front("std-");
96+
const char *StrTable = BuiltinStorage.StringTable;
6597
for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin;
6698
++i) {
67-
if (FuncName == BuiltinInfo[i].Name &&
68-
(bool)strchr(BuiltinInfo[i].Attributes, 'z') == InStdNamespace)
69-
return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
99+
const auto &I = BuiltinStorage.Infos[i];
100+
if (FuncName == getStrFromTable(StrTable, I.Offsets.Name) &&
101+
(bool)strchr(getStrFromTable(StrTable, I.Offsets.Attributes).data(),
102+
'z') == InStdNamespace)
103+
return strchr(getStrFromTable(StrTable, I.Offsets.Attributes).data(),
104+
'f') != nullptr;
70105
}
71106

72107
return false;
73108
}
74109

75110
/// Is this builtin supported according to the given language options?
76-
static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
111+
static bool builtinIsSupported(const char *StrTable,
112+
const Builtin::Info &BuiltinInfo,
77113
const LangOptions &LangOpts) {
114+
auto AttributesStr =
115+
getStrFromTable(StrTable, BuiltinInfo.Offsets.Attributes);
116+
78117
/* Builtins Unsupported */
79-
if (LangOpts.NoBuiltin && strchr(BuiltinInfo.Attributes, 'f') != nullptr)
118+
if (LangOpts.NoBuiltin && strchr(AttributesStr.data(), 'f') != nullptr)
80119
return false;
81120
/* CorBuiltins Unsupported */
82121
if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG))
@@ -123,7 +162,7 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
123162
if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
124163
return false;
125164
/* consteval Unsupported */
126-
if (!LangOpts.CPlusPlus20 && strchr(BuiltinInfo.Attributes, 'G') != nullptr)
165+
if (!LangOpts.CPlusPlus20 && strchr(AttributesStr.data(), 'G') != nullptr)
127166
return false;
128167
return true;
129168
}
@@ -134,20 +173,23 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
134173
void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
135174
const LangOptions& LangOpts) {
136175
// 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);
176+
for (const auto &&[Index, I] :
177+
llvm::enumerate(llvm::ArrayRef(BuiltinStorage.Infos).drop_front()))
178+
if (builtinIsSupported(BuiltinStorage.StringTable, I, LangOpts)) {
179+
Table.get(getStrFromTable(BuiltinStorage.StringTable, I.Offsets.Name))
180+
.setBuiltinID(Index + 1);
140181
}
141182

142183
// 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);
184+
for (const auto &&[Index, I] : llvm::enumerate(TSInfos))
185+
if (builtinIsSupported(TSStrTable, I, LangOpts))
186+
Table.get(getStrFromTable(TSStrTable, I.Offsets.Name))
187+
.setBuiltinID(Index + Builtin::FirstTSBuiltin);
146188

147189
// 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());
190+
for (const auto &&[Index, I] : llvm::enumerate(AuxTSInfos))
191+
Table.get(getStrFromTable(AuxTSStrTable, I.Offsets.Name))
192+
.setBuiltinID(Index + Builtin::FirstTSBuiltin + TSInfos.size());
151193

152194
// Step #4: Unregister any builtins specified by -fno-builtin-foo.
153195
for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
@@ -164,7 +206,7 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
164206
}
165207

166208
unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
167-
const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');
209+
const char *WidthPos = ::strchr(getAttributesString(ID), 'V');
168210
if (!WidthPos)
169211
return 0;
170212

@@ -187,7 +229,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
187229
assert(::toupper(Fmt[0]) == Fmt[1] &&
188230
"Format string is not in the form \"xX\"");
189231

190-
const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);
232+
const char *Like = ::strpbrk(getAttributesString(ID), Fmt);
191233
if (!Like)
192234
return false;
193235

@@ -214,7 +256,7 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
214256

215257
bool Builtin::Context::performsCallback(unsigned ID,
216258
SmallVectorImpl<int> &Encoding) const {
217-
const char *CalleePos = ::strchr(getRecord(ID).Attributes, 'C');
259+
const char *CalleePos = ::strchr(getAttributesString(ID), 'C');
218260
if (!CalleePos)
219261
return false;
220262

clang/lib/Basic/Targets/AArch64.cpp

+32-28
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,39 @@
2626
using namespace clang;
2727
using namespace clang::targets;
2828

29-
static constexpr Builtin::Info BuiltinInfo[] = {
30-
#define BUILTIN(ID, TYPE, ATTRS) \
31-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
32-
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
33-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
34-
#include "clang/Basic/BuiltinsNEON.def"
29+
static constexpr int NumBuiltins =
30+
clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
3531

36-
#define BUILTIN(ID, TYPE, ATTRS) \
37-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
38-
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
39-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
32+
static constexpr auto BuiltinStorage = Builtin::Storage<NumBuiltins>::Make(
33+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
34+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
35+
#include "clang/Basic/BuiltinsNEON.def"
36+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
37+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
4038
#include "clang/Basic/BuiltinsSVE.def"
41-
42-
#define BUILTIN(ID, TYPE, ATTRS) \
43-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
44-
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
45-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
39+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
40+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
4641
#include "clang/Basic/BuiltinsSME.def"
47-
48-
#define BUILTIN(ID, TYPE, ATTRS) \
49-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
50-
#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
51-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},
52-
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
53-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
54-
#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
55-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},
42+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
43+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
44+
#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE
5645
#include "clang/Basic/BuiltinsAArch64.def"
57-
};
46+
, {
47+
#define BUILTIN CLANG_BUILTIN_ENTRY
48+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
49+
#include "clang/Basic/BuiltinsNEON.def"
50+
#define BUILTIN CLANG_BUILTIN_ENTRY
51+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
52+
#include "clang/Basic/BuiltinsSVE.def"
53+
#define BUILTIN CLANG_BUILTIN_ENTRY
54+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
55+
#include "clang/Basic/BuiltinsSME.def"
56+
#define BUILTIN CLANG_BUILTIN_ENTRY
57+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
58+
#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY
59+
#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY
60+
#include "clang/Basic/BuiltinsAArch64.def"
61+
});
5862

5963
void AArch64TargetInfo::setArchFeatures() {
6064
if (*ArchInfo == llvm::AArch64::ARMV8R) {
@@ -697,9 +701,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
697701
}
698702
}
699703

700-
ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
701-
return llvm::ArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
702-
Builtin::FirstTSBuiltin);
704+
std::pair<const char *, ArrayRef<Builtin::Info>>
705+
AArch64TargetInfo::getTargetBuiltinStorage() const {
706+
return {BuiltinStorage.StringTable, BuiltinStorage.Infos};
703707
}
704708

705709
std::optional<std::pair<unsigned, unsigned>>

clang/lib/Basic/Targets/AArch64.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
180180
void getTargetDefines(const LangOptions &Opts,
181181
MacroBuilder &Builder) const override;
182182

183-
ArrayRef<Builtin::Info> getTargetBuiltins() const override;
183+
std::pair<const char *, ArrayRef<Builtin::Info>>
184+
getTargetBuiltinStorage() const override;
184185

185186
std::optional<std::pair<unsigned, unsigned>>
186187
getVScaleRange(const LangOptions &LangOpts) const override;

clang/lib/Basic/Targets/AMDGPU.cpp

+14-9
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,18 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
8888
} // namespace targets
8989
} // namespace clang
9090

91-
static constexpr Builtin::Info BuiltinInfo[] = {
92-
#define BUILTIN(ID, TYPE, ATTRS) \
93-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
94-
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
95-
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
91+
static constexpr int NumBuiltins =
92+
clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin;
93+
94+
static constexpr auto BuiltinStorage = Builtin::Storage<NumBuiltins>::Make(
95+
#define BUILTIN CLANG_BUILTIN_STR_TABLE
96+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
9697
#include "clang/Basic/BuiltinsAMDGPU.def"
97-
};
98+
, {
99+
#define BUILTIN CLANG_BUILTIN_ENTRY
100+
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
101+
#include "clang/Basic/BuiltinsAMDGPU.def"
102+
});
98103

99104
const char *const AMDGPUTargetInfo::GCCRegNames[] = {
100105
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
@@ -266,9 +271,9 @@ void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
266271
!isAMDGCN(getTriple()));
267272
}
268273

269-
ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {
270-
return llvm::ArrayRef(BuiltinInfo,
271-
clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);
274+
std::pair<const char *, ArrayRef<Builtin::Info>>
275+
AMDGPUTargetInfo::getTargetBuiltinStorage() const {
276+
return {BuiltinStorage.StringTable, BuiltinStorage.Infos};
272277
}
273278

274279
void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,

clang/lib/Basic/Targets/AMDGPU.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
257257
StringRef CPU,
258258
const std::vector<std::string> &FeatureVec) const override;
259259

260-
ArrayRef<Builtin::Info> getTargetBuiltins() const override;
260+
std::pair<const char *, ArrayRef<Builtin::Info>>
261+
getTargetBuiltinStorage() const override;
261262

262263
bool useFP16ConversionIntrinsics() const override { return false; }
263264

clang/lib/Basic/Targets/ARC.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ class LLVM_LIBRARY_VISIBILITY ARCTargetInfo : public TargetInfo {
4040
void getTargetDefines(const LangOptions &Opts,
4141
MacroBuilder &Builder) const override;
4242

43-
ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }
43+
std::pair<const char *, ArrayRef<Builtin::Info>>
44+
getTargetBuiltinStorage() const override {
45+
return {nullptr, {}};
46+
}
4447

4548
BuiltinVaListKind getBuiltinVaListKind() const override {
4649
return TargetInfo::VoidPtrBuiltinVaList;

0 commit comments

Comments
 (0)