[StrTable] Add prefixes for x86 builtins.

This requires adding support to the general builtins emission for
producing prefixed builtin infos separately from un-prefixed which is
a bit crufty. But we don't currently have any good way of having a more
refined model than a single hard-coded prefix string per TableGen
emission. Something more powerful and/or elegant is possible, but this
is a fairly minimal first step that at least allows factoring out the
builtin prefix for something like X86.
This commit is contained in:
Chandler Carruth 2025-01-05 15:01:37 +00:00
parent 212ecb9d5c
commit 2ff42bdac3
4 changed files with 82 additions and 8 deletions

View File

@ -86,6 +86,13 @@ def Consteval : Attribute<"EG">;
// indicated by the remaining indices.
class Callback<list<int> ArgIndices> : MultiIndexAttribute<"C", ArgIndices>;
// Prefixes
// ========
class NamePrefix<string spelling> {
string Spelling = spelling;
}
// Builtin kinds
// =============
@ -99,6 +106,9 @@ class Builtin {
bit RequiresUndef = 0;
// Enables builtins to generate `long long` outside of OpenCL and `long` inside.
bit EnableOpenCLLong = 0;
// Requires a common prefix to be prepended. Each generated set of builtins
// can optionally extract one common prefix that is handled separately.
NamePrefix RequiredNamePrefix;
}
class AtomicBuiltin : Builtin;

View File

@ -12,10 +12,13 @@
include "clang/Basic/BuiltinsBase.td"
def X86Prefix : NamePrefix<"__builtin_ia32_">;
class X86Builtin<string prototype> : TargetBuiltin {
let Spellings = ["__builtin_ia32_" # NAME];
let Spellings = [NAME];
let Prototype = prototype;
let EnableOpenCLLong = 1;
let RequiredNamePrefix = X86Prefix; // Adds a prefix to the name.
}
class X86NoPrefixBuiltin<string prototype> : TargetBuiltin {

View File

@ -41,7 +41,14 @@ static constexpr Builtin::Info BuiltinInfos[] = {
#include "clang/Basic/BuiltinsX86.inc"
#undef GET_BUILTIN_INFOS
};
static_assert(std::size(BuiltinInfos) == NumX86Builtins);
static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
#define GET_BUILTIN_PREFIXED_INFOS
#include "clang/Basic/BuiltinsX86.inc"
#undef GET_BUILTIN_PREFIXED_INFOS
};
static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
NumX86Builtins);
} // namespace X86
namespace X86_64 {
@ -54,7 +61,14 @@ static constexpr Builtin::Info BuiltinInfos[] = {
#include "clang/Basic/BuiltinsX86_64.inc"
#undef GET_BUILTIN_INFOS
};
static_assert(std::size(BuiltinInfos) == NumX86_64Builtins);
static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
#define GET_BUILTIN_PREFIXED_INFOS
#include "clang/Basic/BuiltinsX86_64.inc"
#undef GET_BUILTIN_PREFIXED_INFOS
};
static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
NumX86_64Builtins);
} // namespace X86_64
static const char *const GCCRegNames[] = {
@ -1874,13 +1888,19 @@ ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const {
llvm::SmallVector<Builtin::InfosShard>
X86_32TargetInfo::getTargetBuiltins() const {
return {{&X86::BuiltinStrings, X86::BuiltinInfos}};
return {
{&X86::BuiltinStrings, X86::BuiltinInfos},
{&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"},
};
}
llvm::SmallVector<Builtin::InfosShard>
X86_64TargetInfo::getTargetBuiltins() const {
return {
{&X86::BuiltinStrings, X86::BuiltinInfos},
{&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"},
{&X86_64::BuiltinStrings, X86_64::BuiltinInfos},
{&X86_64::BuiltinStrings, X86_64::PrefixedBuiltinInfos,
"__builtin_ia32_"},
};
}

View File

@ -59,7 +59,13 @@ struct Builtin {
const Record *BuiltinRecord;
void EmitEnumerator(llvm::raw_ostream &OS) const {
OS << " BI" << Name << ",\n";
OS << " BI";
// If there is a required name prefix, include its spelling in the
// enumerator.
if (auto *PrefixRecord =
BuiltinRecord->getValueAsOptionalDef("RequiredNamePrefix"))
OS << PrefixRecord->getValueAsString("Spelling");
OS << Name << ",\n";
}
void EmitInfo(llvm::raw_ostream &OS, const StringToOffsetTable &Table) const {
@ -482,17 +488,42 @@ void clang::EmitClangBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
for (const auto *BuiltinRecord :
Records.getAllDerivedDefinitions("AtomicBuiltin"))
collectBuiltins(BuiltinRecord, Builtins);
unsigned NumAtomicBuiltins = Builtins.size();
for (const auto *BuiltinRecord :
Records.getAllDerivedDefinitions("Builtin")) {
if (BuiltinRecord->isSubClassOf("AtomicBuiltin"))
continue;
// Prefixed builtins are also special and we emit them last so they can have
// their own representation that skips the prefix.
if (BuiltinRecord->getValueAsOptionalDef("RequiredNamePrefix"))
continue;
collectBuiltins(BuiltinRecord, Builtins);
}
// Now collect (and count) the prefixed builtins.
unsigned NumPrefixedBuiltins = Builtins.size();
const Record *FirstPrefix = nullptr;
for (const auto *BuiltinRecord :
Records.getAllDerivedDefinitions("Builtin")) {
auto *Prefix = BuiltinRecord->getValueAsOptionalDef("RequiredNamePrefix");
if (!Prefix)
continue;
if (!FirstPrefix)
FirstPrefix = Prefix;
assert(Prefix == FirstPrefix &&
"Multiple distinct prefixes which is not currently supported!");
assert(!BuiltinRecord->isSubClassOf("AtomicBuiltin") &&
"Cannot require a name prefix for an atomic builtin.");
collectBuiltins(BuiltinRecord, Builtins);
}
NumPrefixedBuiltins = Builtins.size() - NumPrefixedBuiltins;
auto AtomicBuiltins = ArrayRef(Builtins).slice(0, NumAtomicBuiltins);
auto UnprefixedBuiltins = ArrayRef(Builtins).drop_back(NumPrefixedBuiltins);
auto PrefixedBuiltins = ArrayRef(Builtins).take_back(NumPrefixedBuiltins);
// Collect strings into a table.
StringToOffsetTable Table;
@ -524,14 +555,24 @@ void clang::EmitClangBuiltins(const RecordKeeper &Records, raw_ostream &OS) {
#endif // GET_BUILTIN_STR_TABLE
)c++";
// Emit a direct set of `Builtin::Info` initializers.
// Emit a direct set of `Builtin::Info` initializers, first for the unprefixed
// builtins and then for the prefixed builtins.
OS << R"c++(
#ifdef GET_BUILTIN_INFOS
)c++";
for (const auto &B : Builtins)
for (const auto &B : UnprefixedBuiltins)
B.EmitInfo(OS, Table);
OS << R"c++(
#endif // GET_BUILTIN_INFOS
)c++";
OS << R"c++(
#ifdef GET_BUILTIN_PREFIXED_INFOS
)c++";
for (const auto &B : PrefixedBuiltins)
B.EmitInfo(OS, Table);
OS << R"c++(
#endif // GET_BUILTIN_PREFIXED_INFOS
)c++";
// Emit X-macros for the atomic builtins to support various custome patterns