aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2024-12-17 19:21:27 +0000
committerChandler Carruth <chandlerc@gmail.com>2025-02-04 18:04:58 +0000
commit212ecb9d5caaa7cc721edd981f36384ddfccfa5d (patch)
treeea504bf9ccc8ed9ab082610568c3d23fc77b19fe
parent64ea3f5a4720105d166b034d5a34d92475579e64 (diff)
downloadllvm-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.h2
-rw-r--r--clang/include/clang/Basic/Builtins.h11
-rw-r--r--clang/include/clang/Basic/IdentifierTable.h3
-rw-r--r--clang/include/clang/Basic/TargetBuiltins.h23
-rw-r--r--clang/lib/AST/StmtPrinter.cpp1
-rw-r--r--clang/lib/Basic/Builtins.cpp26
-rw-r--r--clang/lib/Basic/Targets/BPF.cpp14
-rw-r--r--clang/lib/Basic/Targets/Hexagon.cpp17
-rw-r--r--clang/lib/Basic/Targets/NVPTX.cpp14
-rw-r--r--clang/lib/Basic/Targets/RISCV.cpp16
-rw-r--r--clang/lib/Basic/Targets/SPIR.cpp14
-rw-r--r--clang/lib/Basic/Targets/X86.cpp51
-rw-r--r--clang/lib/Sema/SemaChecking.cpp1
-rw-r--r--clang/test/TableGen/target-builtins-prototype-parser.td18
-rw-r--r--clang/utils/TableGen/ClangBuiltinsEmitter.cpp341
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++";
}