diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2024-12-17 19:21:27 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2025-02-04 18:04:58 +0000 |
commit | 212ecb9d5caaa7cc721edd981f36384ddfccfa5d (patch) | |
tree | ea504bf9ccc8ed9ab082610568c3d23fc77b19fe | |
parent | 64ea3f5a4720105d166b034d5a34d92475579e64 (diff) | |
download | llvm-212ecb9d5caaa7cc721edd981f36384ddfccfa5d.zip llvm-212ecb9d5caaa7cc721edd981f36384ddfccfa5d.tar.gz llvm-212ecb9d5caaa7cc721edd981f36384ddfccfa5d.tar.bz2 |
[StrTable] Teach main builtin TableGen to use direct enums, strings, and info
This moves the main builtins and several targets to use nice generated
string tables and info structures rather than X-macros. Even without
obvious prefixes factored out, the resulting tables are significantly
smaller and much cheaper to compile with out all the X-macro overhead.
This leaves the X-macros in place for atomic builtins which have a wide
range of uses that don't seem reasonable to fold into TableGen.
As future work, these should move to their own file (whether as X-macros
or just generated patterns) so the AST headers don't have to include all
the data for other builtins.
-rw-r--r-- | clang/include/clang/AST/Expr.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Basic/Builtins.h | 11 | ||||
-rw-r--r-- | clang/include/clang/Basic/IdentifierTable.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/TargetBuiltins.h | 23 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Basic/Builtins.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/BPF.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/Hexagon.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/NVPTX.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/RISCV.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/SPIR.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/X86.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 1 | ||||
-rw-r--r-- | clang/test/TableGen/target-builtins-prototype-parser.td | 18 | ||||
-rw-r--r-- | clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 341 |
15 files changed, 313 insertions, 239 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 7be4022..cd584d9 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -6678,7 +6678,6 @@ public: class AtomicExpr : public Expr { public: enum AtomicOp { -#define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, #include "clang/Basic/Builtins.inc" // Avoid trailing comma @@ -6742,7 +6741,6 @@ public: AtomicOp getOp() const { return Op; } StringRef getOpAsString() const { switch (Op) { -#define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case AO##ID: \ return #ID; diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index ba9108d..6d29b43 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -64,9 +64,10 @@ struct HeaderDesc { namespace Builtin { enum ID { - NotBuiltin = 0, // This is not a builtin function. -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, + NotBuiltin = 0, // This is not a builtin function. +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/Builtins.inc" +#undef GET_BUILTIN_ENUMERATORS FirstTSBuiltin }; @@ -77,9 +78,9 @@ struct Info { // Rather than store pointers to the string literals describing these four // aspects of builtins, we store offsets into a common string table. struct StrOffsets { - llvm::StringTable::Offset Name; - llvm::StringTable::Offset Type; - llvm::StringTable::Offset Attributes; + llvm::StringTable::Offset Name = {}; + llvm::StringTable::Offset Type = {}; + llvm::StringTable::Offset Attributes = {}; // Defaults to the empty string offset. llvm::StringTable::Offset Features = {}; diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index e5e6be3..0347880 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -101,8 +101,9 @@ enum class InterestingIdentifier { NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS, NotBuiltin, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/Builtins.inc" +#undef GET_BUILTIN_ENUMERATORS FirstTSBuiltin, NotInterestingIdentifier = 65534 diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index 23463cb..4781054 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -103,8 +103,9 @@ namespace clang { namespace BPF { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, - #define BUILTIN(ID, TYPE, ATTRS) BI##ID, - #include "clang/Basic/BuiltinsBPF.inc" +#define GET_BUILTIN_ENUMERATORS +#include "clang/Basic/BuiltinsBPF.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } @@ -123,8 +124,9 @@ namespace clang { namespace NVPTX { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsNVPTX.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } @@ -143,8 +145,9 @@ namespace clang { namespace SPIRV { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsSPIRV.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } // namespace SPIRV @@ -153,12 +156,14 @@ namespace clang { namespace X86 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsX86.inc" +#undef GET_BUILTIN_ENUMERATORS FirstX86_64Builtin, LastX86CommonBuiltin = FirstX86_64Builtin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsX86_64.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } @@ -192,8 +197,9 @@ namespace clang { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin, LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsRISCV.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } // namespace RISCV @@ -388,8 +394,9 @@ namespace clang { namespace Hexagon { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define GET_BUILTIN_ENUMERATORS #include "clang/Basic/BuiltinsHexagon.inc" +#undef GET_BUILTIN_ENUMERATORS LastTSBuiltin }; } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index bae4134..3ce932a 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1977,7 +1977,6 @@ void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) { void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { const char *Name = nullptr; switch (Node->getOp()) { -#define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case AtomicExpr::AO ## ID: \ Name = #ID "("; \ diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index e5b0ff5..e7829a4 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -29,23 +29,19 @@ const char *HeaderDesc::getName() const { llvm_unreachable("Unknown HeaderDesc::HeaderID enum"); } -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START - // We inject a non-builtin string into the table. - CLANG_BUILTIN_STR_TABLE("not a builtin function", "", "") -#define BUILTIN CLANG_BUILTIN_STR_TABLE +static constexpr unsigned NumBuiltins = Builtin::FirstTSBuiltin; + +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/Builtins.inc" - ; -static_assert(BuiltinStrings.size() < 100'000); - -static constexpr auto BuiltinInfos = - Builtin::MakeInfos<Builtin::FirstTSBuiltin>( - {CLANG_BUILTIN_ENTRY("not a builtin function", "", "") -#define BUILTIN CLANG_BUILTIN_ENTRY -#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY -#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#undef GET_BUILTIN_STR_TABLE + +static constexpr Builtin::Info BuiltinInfos[] = { + Builtin::Info{}, // No-builtin info entry. +#define GET_BUILTIN_INFOS #include "clang/Basic/Builtins.inc" - }); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumBuiltins); std::pair<const Builtin::InfosShard &, const Builtin::Info &> Builtin::Context::getShardAndInfo(unsigned ID) const { diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp index b4504fa..a463de0 100644 --- a/clang/lib/Basic/Targets/BPF.cpp +++ b/clang/lib/Basic/Targets/BPF.cpp @@ -22,16 +22,16 @@ using namespace clang::targets; static constexpr int NumBuiltins = clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin; -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsBPF.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsBPF.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumBuiltins); void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { diff --git a/clang/lib/Basic/Targets/Hexagon.cpp b/clang/lib/Basic/Targets/Hexagon.cpp index acf44ef..c73ecee 100644 --- a/clang/lib/Basic/Targets/Hexagon.cpp +++ b/clang/lib/Basic/Targets/Hexagon.cpp @@ -207,19 +207,16 @@ ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const { static constexpr int NumBuiltins = clang::Hexagon::LastTSBuiltin - Builtin::FirstTSBuiltin; -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsHexagon.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY -#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsHexagon.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumBuiltins); bool HexagonTargetInfo::hasFeature(StringRef Feature) const { std::string VS = "hvxv" + HVXVersion; diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index f20c021..7d13c1f 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -23,16 +23,16 @@ using namespace clang::targets; static constexpr int NumBuiltins = clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin; -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsNVPTX.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({ -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsNVPTX.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumBuiltins); const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index c4317a1..b4aa320 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -277,18 +277,16 @@ static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos = }; } // namespace RVVSiFive -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsRISCV.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumRISCVBuiltins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsRISCV.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins); llvm::SmallVector<Builtin::InfosShard> RISCVTargetInfo::getTargetBuiltins() const { diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp index a242fd8..5c076f6 100644 --- a/clang/lib/Basic/Targets/SPIR.cpp +++ b/clang/lib/Basic/Targets/SPIR.cpp @@ -23,16 +23,16 @@ using namespace clang::targets; static constexpr int NumBuiltins = clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin; -static constexpr llvm::StringTable BuiltinStrings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsSPIRV.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsSPIRV.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumBuiltins); llvm::SmallVector<Builtin::InfosShard> SPIRVTargetInfo::getTargetBuiltins() const { diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 1bb5f78..79b3bda 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -31,36 +31,31 @@ static constexpr int NumX86_64Builtins = static constexpr int NumBuiltins = X86::LastTSBuiltin - Builtin::FirstTSBuiltin; static_assert(NumBuiltins == (NumX86Builtins + NumX86_64Builtins)); -static constexpr llvm::StringTable BuiltinX86Strings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE -#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE +namespace X86 { +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsX86.inc" - ; +#undef GET_BUILTIN_STR_TABLE -static constexpr llvm::StringTable BuiltinX86_64Strings = - CLANG_BUILTIN_STR_TABLE_START -#define BUILTIN CLANG_BUILTIN_STR_TABLE -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE -#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE -#include "clang/Basic/BuiltinsX86_64.inc" - ; - -static constexpr auto BuiltinX86Infos = Builtin::MakeInfos<NumX86Builtins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY -#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS #include "clang/Basic/BuiltinsX86.inc" -}); +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumX86Builtins); +} // namespace X86 -static constexpr auto BuiltinX86_64Infos = - Builtin::MakeInfos<NumX86_64Builtins>({ -#define BUILTIN CLANG_BUILTIN_ENTRY -#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY -#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY +namespace X86_64 { +#define GET_BUILTIN_STR_TABLE #include "clang/Basic/BuiltinsX86_64.inc" - }); +#undef GET_BUILTIN_STR_TABLE + +static constexpr Builtin::Info BuiltinInfos[] = { +#define GET_BUILTIN_INFOS +#include "clang/Basic/BuiltinsX86_64.inc" +#undef GET_BUILTIN_INFOS +}; +static_assert(std::size(BuiltinInfos) == NumX86_64Builtins); +} // namespace X86_64 static const char *const GCCRegNames[] = { "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", @@ -1879,13 +1874,13 @@ ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const { llvm::SmallVector<Builtin::InfosShard> X86_32TargetInfo::getTargetBuiltins() const { - return {{&BuiltinX86Strings, BuiltinX86Infos}}; + return {{&X86::BuiltinStrings, X86::BuiltinInfos}}; } llvm::SmallVector<Builtin::InfosShard> X86_64TargetInfo::getTargetBuiltins() const { return { - {&BuiltinX86Strings, BuiltinX86Infos}, - {&BuiltinX86_64Strings, BuiltinX86_64Infos}, + {&X86::BuiltinStrings, X86::BuiltinInfos}, + {&X86_64::BuiltinStrings, X86_64::BuiltinInfos}, }; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b345e40..66c233d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2451,7 +2451,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CheckNonNullArgument(*this, TheCall->getArg(0), TheCall->getExprLoc()); break; } -#define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ return AtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td index a753f90..451f1a1 100644 --- a/clang/test/TableGen/target-builtins-prototype-parser.td +++ b/clang/test/TableGen/target-builtins-prototype-parser.td @@ -10,55 +10,55 @@ include "clang/Basic/BuiltinsBase.td" def : Builtin { -// CHECK: BUILTIN(__builtin_01, "E8idE4b", "") +// CHECK: Builtin::Info{{.*}} __builtin_01 {{.*}} /* E8idE4b */ let Prototype = "_ExtVector<8,int>(double, _ExtVector<4, bool>)"; let Spellings = ["__builtin_01"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_02, "E8UiE4s", "") +// CHECK: Builtin::Info{{.*}} __builtin_02 {{.*}} /* E8UiE4s */ let Prototype = "_ExtVector<8,unsigned int>(_ExtVector<4, short>)"; let Spellings = ["__builtin_02"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_03, "di", "") +// CHECK: Builtin::Info{{.*}} __builtin_03 {{.*}} /* di */ let Prototype = "double(int)"; let Spellings = ["__builtin_03"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_04, "diIUi", "") +// CHECK: Builtin::Info{{.*}} __builtin_04 {{.*}} /* diIUi */ let Prototype = "double(int, _Constant unsigned int)"; let Spellings = ["__builtin_04"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_05, "v&v&", "") +// CHECK: Builtin::Info{{.*}} __builtin_05 {{.*}} /* v&v& */ let Prototype = "void&(void&)"; let Spellings = ["__builtin_05"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_06, "v*v*cC*.", "") +// CHECK: Builtin::Info{{.*}} __builtin_06 {{.*}} /* v*v*cC*. */ let Prototype = "void*(void*, char const*, ...)"; let Spellings = ["__builtin_06"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_07, "E8iE4dE4b.", "") +// CHECK: Builtin::Info{{.*}} __builtin_07 {{.*}} /* E8iE4dE4b. */ let Prototype = "_ExtVector<8, int>(_ExtVector<4,double>, _ExtVector<4, bool>, ...)"; let Spellings = ["__builtin_07"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_08, "di*R", "") +// CHECK: Builtin::Info{{.*}} __builtin_08 {{.*}} /* di*R */ let Prototype = "double(int * restrict)"; let Spellings = ["__builtin_08"]; } def : Builtin { -// CHECK: BUILTIN(__builtin_09, "V2yy", "") +// CHECK: Builtin::Info{{.*}} __builtin_09 {{.*}} /* V2yy */ let Prototype = "_Vector<2, __bf16>(__bf16)"; let Spellings = ["__builtin_09"]; } diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp index 5c5f011..e6c7490 100644 --- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp +++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp @@ -15,7 +15,9 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" +#include <sstream> using namespace llvm; @@ -29,6 +31,119 @@ enum class BuiltinType { TargetLibBuiltin, }; +class HeaderNameParser { +public: + HeaderNameParser(const Record *Builtin) { + for (char c : Builtin->getValueAsString("Header")) { + if (std::islower(c)) + HeaderName += static_cast<char>(std::toupper(c)); + else if (c == '.' || c == '_' || c == '/' || c == '-') + HeaderName += '_'; + else + PrintFatalError(Builtin->getLoc(), "Unexpected header name"); + } + } + + void Print(raw_ostream &OS) const { OS << HeaderName; } + +private: + std::string HeaderName; +}; + +struct Builtin { + BuiltinType BT; + std::string Name; + std::string Type; + std::string Attributes; + + const Record *BuiltinRecord; + + void EmitEnumerator(llvm::raw_ostream &OS) const { + OS << " BI" << Name << ",\n"; + } + + void EmitInfo(llvm::raw_ostream &OS, const StringToOffsetTable &Table) const { + OS << " Builtin::Info{Builtin::Info::StrOffsets{" + << Table.GetStringOffset(Name) << " /* " << Name << " */, " + << Table.GetStringOffset(Type) << " /* " << Type << " */, " + << Table.GetStringOffset(Attributes) << " /* " << Attributes << " */, "; + if (BT == BuiltinType::TargetBuiltin) { + const auto &Features = BuiltinRecord->getValueAsString("Features"); + OS << Table.GetStringOffset(Features) << " /* " << Features << " */"; + } else { + OS << "0"; + } + OS << "}, "; + if (BT == BuiltinType::LibBuiltin || BT == BuiltinType::TargetLibBuiltin) { + OS << "HeaderDesc::"; + HeaderNameParser{BuiltinRecord}.Print(OS); + } else { + OS << "HeaderDesc::NO_HEADER"; + } + OS << ", "; + if (BT == BuiltinType::LibBuiltin || BT == BuiltinType::LangBuiltin || + BT == BuiltinType::TargetLibBuiltin) { + OS << BuiltinRecord->getValueAsString("Languages"); + } else { + OS << "ALL_LANGUAGES"; + } + OS << "},\n"; + } + + void EmitXMacro(llvm::raw_ostream &OS) const { + if (BuiltinRecord->getValueAsBit("RequiresUndef")) + OS << "#undef " << Name << '\n'; + switch (BT) { + case BuiltinType::LibBuiltin: + OS << "LIBBUILTIN"; + break; + case BuiltinType::LangBuiltin: + OS << "LANGBUILTIN"; + break; + case BuiltinType::Builtin: + OS << "BUILTIN"; + break; + case BuiltinType::AtomicBuiltin: + OS << "ATOMIC_BUILTIN"; + break; + case BuiltinType::TargetBuiltin: + OS << "TARGET_BUILTIN"; + break; + case BuiltinType::TargetLibBuiltin: + OS << "TARGET_HEADER_BUILTIN"; + break; + } + + OS << "(" << Name << ", \"" << Type << "\", \"" << Attributes << "\""; + + switch (BT) { + case BuiltinType::LibBuiltin: { + OS << ", "; + HeaderNameParser{BuiltinRecord}.Print(OS); + [[fallthrough]]; + } + case BuiltinType::LangBuiltin: { + OS << ", " << BuiltinRecord->getValueAsString("Languages"); + break; + } + case BuiltinType::TargetLibBuiltin: { + OS << ", "; + HeaderNameParser{BuiltinRecord}.Print(OS); + OS << ", " << BuiltinRecord->getValueAsString("Languages"); + [[fallthrough]]; + } + case BuiltinType::TargetBuiltin: { + OS << ", \"" << BuiltinRecord->getValueAsString("Features") << "\""; + break; + } + case BuiltinType::AtomicBuiltin: + case BuiltinType::Builtin: + break; + } + OS << ")\n"; + } +}; + class PrototypeParser { public: PrototypeParser(StringRef Substitution, const Record *Builtin) @@ -37,6 +152,8 @@ public: ParsePrototype(Builtin->getValueAsString("Prototype")); } + std::string takeTypeString() && { return std::move(Type); } + private: void ParsePrototype(StringRef Prototype) { Prototype = Prototype.trim(); @@ -243,37 +360,15 @@ private: } } -public: - void Print(raw_ostream &OS) const { OS << ", \"" << Type << '\"'; } - -private: SMLoc Loc; StringRef Substitution; bool EnableOpenCLLong; std::string Type; }; -class HeaderNameParser { -public: - HeaderNameParser(const Record *Builtin) { - for (char c : Builtin->getValueAsString("Header")) { - if (std::islower(c)) - HeaderName += static_cast<char>(std::toupper(c)); - else if (c == '.' || c == '_' || c == '/' || c == '-') - HeaderName += '_'; - else - PrintFatalError(Builtin->getLoc(), "Unexpected header name"); - } - } - - void Print(raw_ostream &OS) const { OS << HeaderName; } - -private: - std::string HeaderName; -}; - -void PrintAttributes(const Record *Builtin, BuiltinType BT, raw_ostream &OS) { - OS << '\"'; +std::string renderAttributes(const Record *Builtin, BuiltinType BT) { + std::string Attributes; + raw_string_ostream OS(Attributes); if (Builtin->isSubClassOf("LibBuiltin")) { if (BT == BuiltinType::LibBuiltin) { OS << 'f'; @@ -302,63 +397,18 @@ void PrintAttributes(const Record *Builtin, BuiltinType BT, raw_ostream &OS) { OS << '>'; } } - OS << '\"'; + return Attributes; } -void EmitBuiltinDef(raw_ostream &OS, StringRef Substitution, - const Record *Builtin, Twine Spelling, BuiltinType BT) { - if (Builtin->getValueAsBit("RequiresUndef")) - OS << "#undef " << Spelling << '\n'; - switch (BT) { - case BuiltinType::LibBuiltin: - OS << "LIBBUILTIN"; - break; - case BuiltinType::LangBuiltin: - OS << "LANGBUILTIN"; - break; - case BuiltinType::Builtin: - OS << "BUILTIN"; - break; - case BuiltinType::AtomicBuiltin: - OS << "ATOMIC_BUILTIN"; - break; - case BuiltinType::TargetBuiltin: - OS << "TARGET_BUILTIN"; - break; - case BuiltinType::TargetLibBuiltin: - OS << "TARGET_HEADER_BUILTIN"; - break; - } - - OS << "(" << Spelling; - PrototypeParser{Substitution, Builtin}.Print(OS); - OS << ", "; - PrintAttributes(Builtin, BT, OS); - - switch (BT) { - case BuiltinType::LibBuiltin: { - OS << ", "; - HeaderNameParser{Builtin}.Print(OS); - [[fallthrough]]; - } - case BuiltinType::LangBuiltin: { - OS << ", " << Builtin->getValueAsString("Languages"); - break; - } - case BuiltinType::TargetLibBuiltin: { - OS << ", "; - HeaderNameParser{Builtin}.Print(OS); - OS << ", " << Builtin->getValueAsString("Languages"); - [[fallthrough]]; - } - case BuiltinType::TargetBuiltin: - OS << ", \"" << Builtin->getValueAsString("Features") << "\""; - break; - case BuiltinType::AtomicBuiltin: - case BuiltinType::Builtin: - break; - } - OS << ")\n"; +Builtin buildBuiltin(StringRef Substitution, const Record *BuiltinRecord, + Twine Spelling, BuiltinType BT) { + Builtin B; + B.BT = BT; + B.Name = Spelling.str(); + B.Type = PrototypeParser(Substitution, BuiltinRecord).takeTypeString(); + B.Attributes = renderAttributes(BuiltinRecord, BT); + B.BuiltinRecord = BuiltinRecord; + return B; } struct TemplateInsts { @@ -384,10 +434,11 @@ TemplateInsts getTemplateInsts(const Record *R) { return temp; } -void EmitBuiltin(raw_ostream &OS, const Record *Builtin) { +void collectBuiltins(const Record *BuiltinRecord, + SmallVectorImpl<Builtin> &Builtins) { TemplateInsts Templates = {}; - if (Builtin->isSubClassOf("Template")) { - Templates = getTemplateInsts(Builtin); + if (BuiltinRecord->isSubClassOf("Template")) { + Templates = getTemplateInsts(BuiltinRecord); } else { Templates.Affix.emplace_back(); Templates.Substitution.emplace_back(); @@ -395,26 +446,28 @@ void EmitBuiltin(raw_ostream &OS, const Record *Builtin) { for (auto [Substitution, Affix] : zip(Templates.Substitution, Templates.Affix)) { - for (StringRef Spelling : Builtin->getValueAsListOfStrings("Spellings")) { + for (StringRef Spelling : + BuiltinRecord->getValueAsListOfStrings("Spellings")) { auto FullSpelling = (Templates.IsPrefix ? Affix + Spelling : Spelling + Affix).str(); BuiltinType BT = BuiltinType::Builtin; - if (Builtin->isSubClassOf("AtomicBuiltin")) { + if (BuiltinRecord->isSubClassOf("AtomicBuiltin")) { BT = BuiltinType::AtomicBuiltin; - } else if (Builtin->isSubClassOf("LangBuiltin")) { + } else if (BuiltinRecord->isSubClassOf("LangBuiltin")) { BT = BuiltinType::LangBuiltin; - } else if (Builtin->isSubClassOf("TargetLibBuiltin")) { + } else if (BuiltinRecord->isSubClassOf("TargetLibBuiltin")) { BT = BuiltinType::TargetLibBuiltin; - } else if (Builtin->isSubClassOf("TargetBuiltin")) { + } else if (BuiltinRecord->isSubClassOf("TargetBuiltin")) { BT = BuiltinType::TargetBuiltin; - } else if (Builtin->isSubClassOf("LibBuiltin")) { + } else if (BuiltinRecord->isSubClassOf("LibBuiltin")) { BT = BuiltinType::LibBuiltin; - if (Builtin->getValueAsBit("AddBuiltinPrefixedAlias")) - EmitBuiltinDef(OS, Substitution, Builtin, - std::string("__builtin_") + FullSpelling, - BuiltinType::Builtin); + if (BuiltinRecord->getValueAsBit("AddBuiltinPrefixedAlias")) + Builtins.push_back(buildBuiltin( + Substitution, BuiltinRecord, + std::string("__builtin_") + FullSpelling, BuiltinType::Builtin)); } - EmitBuiltinDef(OS, Substitution, Builtin, FullSpelling, BT); + Builtins.push_back( + buildBuiltin(Substitution, BuiltinRecord, FullSpelling, BT)); } } } @@ -423,47 +476,77 @@ void EmitBuiltin(raw_ostream &OS, const Record *Builtin) { void clang::EmitClangBuiltins(const RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("List of builtins that Clang recognizes", OS); - OS << R"c++( -#if defined(BUILTIN) && !defined(LIBBUILTIN) -# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) -#endif - -#if defined(BUILTIN) && !defined(LANGBUILTIN) -# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) -#endif - -// Some of our atomics builtins are handled by AtomicExpr rather than -// as normal builtin CallExprs. This macro is used for such builtins. -#ifndef ATOMIC_BUILTIN -# define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS) -#endif - -#if defined(BUILTIN) && !defined(TARGET_BUILTIN) -# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) -#endif - -#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN) -# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS) -#endif -)c++"; + SmallVector<Builtin> Builtins; + // AtomicBuiltins are order dependent. Emit them first to make manual checking + // easier and so we can build a special atomic builtin X-macro. + for (const auto *BuiltinRecord : + Records.getAllDerivedDefinitions("AtomicBuiltin")) + collectBuiltins(BuiltinRecord, Builtins); - // AtomicBuiltins are order dependent - // emit them first to make manual checking easier - for (const auto *Builtin : Records.getAllDerivedDefinitions("AtomicBuiltin")) - EmitBuiltin(OS, Builtin); + unsigned NumAtomicBuiltins = Builtins.size(); - for (const auto *Builtin : Records.getAllDerivedDefinitions("Builtin")) { - if (Builtin->isSubClassOf("AtomicBuiltin")) + for (const auto *BuiltinRecord : + Records.getAllDerivedDefinitions("Builtin")) { + if (BuiltinRecord->isSubClassOf("AtomicBuiltin")) continue; - EmitBuiltin(OS, Builtin); + collectBuiltins(BuiltinRecord, Builtins); + } + + auto AtomicBuiltins = ArrayRef(Builtins).slice(0, NumAtomicBuiltins); + + // Collect strings into a table. + StringToOffsetTable Table; + Table.GetOrAddStringOffset(""); + for (const auto &B : Builtins) { + Table.GetOrAddStringOffset(B.Name); + Table.GetOrAddStringOffset(B.Type); + Table.GetOrAddStringOffset(B.Attributes); + if (B.BT == BuiltinType::TargetBuiltin) + Table.GetOrAddStringOffset(B.BuiltinRecord->getValueAsString("Features")); } + // Emit enumerators. + OS << R"c++( +#ifdef GET_BUILTIN_ENUMERATORS +)c++"; + for (const auto &B : Builtins) + B.EmitEnumerator(OS); + OS << R"c++( +#endif // GET_BUILTIN_ENUMERATORS +)c++"; + + // Emit a string table that can be referenced for these builtins. + OS << R"c++( +#ifdef GET_BUILTIN_STR_TABLE +)c++"; + Table.EmitStringTableDef(OS, "BuiltinStrings"); + OS << R"c++( +#endif // GET_BUILTIN_STR_TABLE +)c++"; + + // Emit a direct set of `Builtin::Info` initializers. + OS << R"c++( +#ifdef GET_BUILTIN_INFOS +)c++"; + for (const auto &B : Builtins) + B.EmitInfo(OS, Table); + OS << R"c++( +#endif // GET_BUILTIN_INFOS +)c++"; + + // Emit X-macros for the atomic builtins to support various custome patterns + // used exclusively with those builtins. + // + // FIXME: We should eventually move this to a separate file so that users + // don't need to include the full set of builtins. + OS << R"c++( +#ifdef ATOMIC_BUILTIN +)c++"; + for (const auto &Builtin : AtomicBuiltins) { + Builtin.EmitXMacro(OS); + } OS << R"c++( +#endif // ATOMIC_BUILTIN #undef ATOMIC_BUILTIN -#undef BUILTIN -#undef LIBBUILTIN -#undef LANGBUILTIN -#undef TARGET_BUILTIN -#undef TARGET_HEADER_BUILTIN )c++"; } |