[llvm-branch-commits] [clang] [CIR] Derive lowering attr names from cppClassName, not the def name (PR #220891)
Henrich Lauko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Sep 3 04:31:34 PDT 2026
https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/220891
CIRLoweringEmitter built its CXX_ABI_ALWAYS_LEGAL_ATTRS entries by calling
GetOpCppClassName on an attribute record, which splits the TableGen def name
at the first underscore. That works only while every def happens to be named
CIR_<CppClassName>Attr. When one is not, the emitter silently writes an
`isa<cir::Whatever>` for a class that does not exist, so the failure lands as
a compile error in generated code with no hint at the cause. The constraint
was real enough that CIREnumAttr.td had to document it.
Attributes already carry the authoritative name in cppClassName, and
GenerateAttrToValueVisitor two functions down was reading it correctly.
Factor that out as GetAttrCppClassRef and use it for the enum attributes and
the plain CIR attributes as well, which also drops the hardcoded `cir::` in
favour of the dialect's own cppNamespace. GetOpCppClassName stays for
operations, whose names are derived that way.
The def name is now free, so the paragraph in CIREnumAttr.td warning that it
is not goes away.
NFC, and checkable rather than argued. No CIR attribute overrides
cppClassName, so the derived and declared names agree everywhere today, and
the generated CIRLowering.inc is byte-identical.
---
Stacked on #220890. Based on `users/xlauko/cir-enum-11-drop-enum-cruft`, so the diff shown is this commit alone.
>From 1a652cadd4069c32b26e64be7c2ff81e6e932b6b Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Thu, 3 Sep 2026 11:29:23 +0000
Subject: [PATCH] [CIR] Derive lowering attr names from cppClassName, not the
def name
CIRLoweringEmitter built its CXX_ABI_ALWAYS_LEGAL_ATTRS entries by calling
GetOpCppClassName on an attribute record, which splits the TableGen def name
at the first underscore. That works only while every def happens to be named
CIR_<CppClassName>Attr. When one is not, the emitter silently writes an
`isa<cir::Whatever>` for a class that does not exist, so the failure lands as
a compile error in generated code with no hint at the cause. The constraint
was real enough that CIREnumAttr.td had to document it.
Attributes already carry the authoritative name in cppClassName, and
GenerateAttrToValueVisitor two functions down was reading it correctly.
Factor that out as GetAttrCppClassRef and use it for the enum attributes and
the plain CIR attributes as well, which also drops the hardcoded `cir::` in
favour of the dialect's own cppNamespace. GetOpCppClassName stays for
operations, whose names are derived that way.
The def name is now free, so the paragraph in CIREnumAttr.td warning that it
is not goes away.
NFC, and checkable rather than argued. No CIR attribute overrides
cppClassName, so the derived and declared names agree everywhere today, and
the generated CIRLowering.inc is byte-identical.
---
.../clang/CIR/Dialect/IR/CIREnumAttr.td | 4 ---
clang/utils/TableGen/CIRLoweringEmitter.cpp | 26 ++++++++++++-------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 3659eb71257f8..26bccc6090b37 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -46,10 +46,6 @@ class CIR_I32BitEnumAttr<string name, string summary,
// must therefore wrap the argument in the `enum` assembly format directive,
// as in `enum($cleanupKind)`. Referring to the argument directly would print
// the stripped attribute body, i.e. `<all>` including the delimiters.
-//
-// The def name is not free: `CIRLoweringEmitter` derives an `isa<cir::...>`
-// entry for `CXXABILowering.cpp` by dropping the prefix up to the first
-// underscore, so a def must be named `CIR_<CppClassName>`.
class CIR_EnumAttr<EnumAttrInfo info, string name = "", list<Trait> traits = []>
: EnumAttr<CIR_Dialect, info, name, traits> {
let assemblyFormat = "`<` $value `>`";
diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index f67c37b9e1870..39be43a337c74 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -62,6 +62,19 @@ std::string GetOpCppClassName(const Record *OpRecord) {
return CppClassName.str();
}
+// Returns the namespace-qualified C++ class name of an attribute. Unlike
+// operations, attributes carry the authoritative name in cppClassName, so the
+// def name is free to differ from it.
+std::string GetAttrCppClassRef(const Record *AttrRecord) {
+ StringRef Ns =
+ AttrRecord->getValueAsDef("dialect")->getValueAsString("cppNamespace");
+ Ns.consume_front("::");
+ std::string CppClassRef = Ns.str();
+ CppClassRef += "::";
+ CppClassRef += AttrRecord->getValueAsString("cppClassName");
+ return CppClassRef;
+}
+
std::string GetOpABILoweringPatternName(llvm::StringRef OpName) {
std::string Name = "CIR";
Name += OpName;
@@ -286,19 +299,13 @@ void Generate(const Record *OpRecord) {
}
void GenerateCIREnumAttrs(const Record *Record) {
- std::string OpName = GetOpCppClassName(Record);
// EnumAttr is in a separate hierarchy, so we have to set these separately, as
// they never have an 'illegal' CXXABI type in them.
- CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
+ CXXABILoweringAttrAlwaysLegal.push_back(GetAttrCppClassRef(Record));
}
void GenerateAttrToValueVisitor(const Record *Rec) {
- const Record *DialectRec = Rec->getValueAsDef("dialect");
- llvm::StringRef Ns = DialectRec->getValueAsString("cppNamespace");
- Ns.consume_front("::");
- std::string CppClassRef = Ns.str();
- CppClassRef += "::";
- CppClassRef += Rec->getValueAsString("cppClassName");
+ std::string CppClassRef = GetAttrCppClassRef(Rec);
std::string CodeBuffer;
llvm::raw_string_ostream Code(CodeBuffer);
@@ -327,9 +334,8 @@ void GenerateAttrToValueVisitFunc() {
}
void GenerateCIRAttrs(const Record *Record) {
- std::string OpName = GetOpCppClassName(Record);
if (!Record->getValueAsBit("canHaveIllegalCXXABIType"))
- CXXABILoweringAttrAlwaysLegal.push_back("cir::" + OpName);
+ CXXABILoweringAttrAlwaysLegal.push_back(GetAttrCppClassRef(Record));
if (Record->getValueAsBit("hasAttrToValueLowering"))
GenerateAttrToValueVisitor(Record);
}
More information about the llvm-branch-commits
mailing list