[llvm-branch-commits] [clang] [CIR][CIRGen] Introduce ExtraFuncAttr to FuncOp (PR #186331)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 13 00:50:07 PDT 2026
https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/186331
>From f137fbd75a779b2f903c4d9d5643f804169c132e Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Fri, 13 Mar 2026 13:01:05 +0530
Subject: [PATCH] [CIR][CIRGen] Introduce ExtraFuncAttr to FuncOp
---
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 22 +++++++++++++++++++
clang/include/clang/CIR/Dialect/IR/CIROps.td | 6 +++++
clang/include/clang/CIR/MissingFeatures.h | 1 -
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 3 +++
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 3 +++
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 10 ++++-----
clang/lib/CIR/CodeGen/CIRGenVTables.cpp | 3 +++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 21 ++++++++++++++++++
.../CIR/Dialect/Transforms/EHABILowering.cpp | 4 ++++
.../Dialect/Transforms/LoweringPrepare.cpp | 5 +++--
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 ++++++++++--
.../Lowering/DirectToLLVM/LowerToLLVMIR.cpp | 13 ++++++++++-
12 files changed, 93 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 16d32802d7c2c..a3a1d8c329abc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -943,6 +943,28 @@ def CIR_VisibilityAttr : CIR_EnumAttr<CIR_VisibilityKind, "visibility"> {
}];
}
+//===----------------------------------------------------------------------===//
+// ExtraFuncAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_ExtraFuncAttr : CIR_Attr<"ExtraFuncAttributes", "extra"> {
+ let summary = "Represents aggregated attributes for a function";
+ let description = [{
+ This is a wrapper of attribute dictionary that contains extra attributes of
+ a function.
+ }];
+
+ let parameters = (ins "mlir::DictionaryAttr":$elements);
+
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "mlir::DictionaryAttr":$elements), [{
+ return $_get(elements.getContext(), elements);
+ }]>
+ ];
+
+ let assemblyFormat = [{ `(` $elements `)` }];
+}
+
//===----------------------------------------------------------------------===//
// GloblCtorAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d10bed40e75d4..7306a0b8fa3cc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3418,6 +3418,11 @@ def CIR_FuncOp : CIR_Op<"func", [
without a prototype and, consequently, may contain calls with invalid
arguments and undefined behavior.
+ The `extra_attrs`, which is an aggregate of function-specific attributes is
+ required and mandatory to describle additional attributes that are not listed
+ above. Though mandatory, the prining of the attribute can be omitted if it is
+ empty.
+
The `global_ctor` keyword indicates whether a function should execute before
`main()` function, as specified by `__attribute__((constructor))`. An
execution priority can also be specified `global_ctor(<priority>)`.
@@ -3473,6 +3478,7 @@ def CIR_FuncOp : CIR_Op<"func", [
CIR_GlobalLinkageKind,
"cir::GlobalLinkageKind::ExternalLinkage"
>:$linkage,
+ CIR_ExtraFuncAttr:$extra_attrs,
OptionalAttr<StrAttr>:$sym_visibility,
UnitAttr:$comdat,
OptionalAttr<DictArrayAttr>:$arg_attrs,
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index b7b4d73afa0f8..4000446862c53 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -75,7 +75,6 @@ struct MissingFeatures {
static bool opFuncColdHotAttr() { return false; }
static bool opFuncCPUAndFeaturesAttributes() { return false; }
static bool opFuncExceptions() { return false; }
- static bool opFuncExtraAttrs() { return false; }
static bool opFuncMaybeHandleStaticInExternC() { return false; }
static bool opFuncMinSizeAttr() { return false; }
static bool opFuncMultipleReturnVals() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1f08ba773dfb5..186b1e861cf2b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1975,6 +1975,9 @@ CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
&cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
clone.setSymVisibility("private");
clone.setInlineKind(cir::InlineKind::AlwaysInline);
+ mlir::NamedAttrList attrs;
+ clone.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ attrs.getDictionary(&cgm.getMLIRContext())));
}
return CIRGenCallee::forDirect(clone, gd);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 71a647e37ea52..81ec4c5205baa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -720,6 +720,9 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
clone.setSymVisibility("private");
clone.setInlineKind(cir::InlineKind::AlwaysInline);
+ mlir::NamedAttrList attrs;
+ clone.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ attrs.getDictionary(builder.getContext())));
}
fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
fn.setSymVisibility("private");
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fd08cdae37881..5514257c052e5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2356,11 +2356,7 @@ void CIRGenModule::setCIRFunctionAttributes(GlobalDecl globalDecl,
cir::CallingConv callingConv;
cir::SideEffect sideEffect;
- // TODO(cir): The current list should be initialized with the extra function
- // attributes, but we don't have those yet. For now, the PAL is initialized
- // with nothing.
- assert(!cir::MissingFeatures::opFuncExtraAttrs());
- // Initialize PAL with existing attributes to merge attributes.
+ // TODO(cir): Move all function attributes into extra_attrs.
mlir::NamedAttrList pal{};
std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
mlir::NamedAttrList retAttrs{};
@@ -2694,7 +2690,9 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
mlir::SymbolTable::setSymbolVisibility(
func, mlir::SymbolTable::Visibility::Private);
- assert(!cir::MissingFeatures::opFuncExtraAttrs());
+ // Initialize with empty dict of extra attributes.
+ func.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ &getMLIRContext(), mlir::DictionaryAttr::get(&getMLIRContext())));
// Mark C++ special member functions (Constructor, Destructor etc.)
setCXXSpecialMemberAttr(func, funcDecl);
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index cdc83a3ede3c7..4e94f13f01753 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -858,6 +858,9 @@ cir::FuncOp CIRGenVTables::maybeEmitThunk(GlobalDecl gd,
thunkFn =
cir::FuncOp::create(cgm.getBuilder(), thunk->getLoc(), name.str(),
thunkFnTy, cir::GlobalLinkageKind::ExternalLinkage);
+ mlir::NamedAttrList attrs;
+ thunkFn.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ attrs.getDictionary(cgm.getBuilder().getContext())));
cgm.setCIRFunctionAttributes(md, fnInfo, thunkFn, /*isThunk=*/false);
if (!oldThunkFn->use_empty())
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8d2990af5de8c..e3e67edbc7c3d 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2153,6 +2153,21 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
hasAlias = true;
}
+ // If extra func attributes are present, parse them.
+ NamedAttrList extraAttrs;
+ if (::mlir::succeeded(parser.parseOptionalKeyword("extra"))) {
+ if (parser.parseLParen().failed())
+ return failure();
+ if (parser.parseOptionalAttrDict(extraAttrs).failed())
+ return failure();
+ if (parser.parseRParen().failed())
+ return failure();
+ }
+ state.addAttribute(
+ getExtraAttrsAttrName(state.name),
+ cir::ExtraFuncAttributesAttr::get(
+ parser.getContext(), extraAttrs.getDictionary(parser.getContext())));
+
mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
if (parser.parseOptionalKeyword("personality").succeeded()) {
if (parser.parseLParen().failed())
@@ -2413,6 +2428,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
function_interface_impl::printFunctionAttributes(
p, *this, cir::FuncOp::getAttributeNames());
+ if (!getExtraAttrs().getElements().empty()) {
+ p << " extra(";
+ p.printOptionalAttrDict(getExtraAttrs().getElements().getValue());
+ p << ')';
+ }
+
// Print the body if this is not an external function.
Region &body = getOperation()->getRegion(0);
if (!body.empty()) {
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index d5d10b1b251be..e0be09d0151f5 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -25,6 +25,7 @@
#include "PassDetail.h"
#include "mlir/IR/Builders.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -61,6 +62,9 @@ static cir::FuncOp getOrCreateRuntimeFuncDecl(mlir::ModuleOp mod,
auto funcOp = cir::FuncOp::create(builder, loc, name, funcTy);
funcOp.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
funcOp.setPrivate();
+ mlir::NamedAttrList attrs;
+ funcOp.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ attrs.getDictionary(builder.getContext())));
return funcOp;
}
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 232d320d71f37..8ad88c3336e89 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -334,8 +334,9 @@ cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
mlir::SymbolTable::setSymbolVisibility(
f, mlir::SymbolTable::Visibility::Private);
-
- assert(!cir::MissingFeatures::opFuncExtraAttrs());
+ mlir::NamedAttrList attrs;
+ f.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
+ attrs.getDictionary(builder.getContext())));
}
return f;
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 9c68248d5dede..d6aca6e84bc4a 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1881,7 +1881,6 @@ static void lowerCallAttributes(cir::CIRCallOpInterface op,
attr.getName() == CIRDialect::getNoReturnAttrName())
continue;
- assert(!cir::MissingFeatures::opFuncExtraAttrs());
result.push_back(attr);
}
}
@@ -2386,7 +2385,18 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
attr.getName() == func.getResAttrsAttrName())))
continue;
- assert(!cir::MissingFeatures::opFuncExtraAttrs());
+ // Propagate extra function attributes to LLVM via amendOperation. Rename
+ // with "cir." prefix so CIRDialectLLVMIRTranslationInterface picks them up.
+ // Skip empty extra_attrs to avoid leaking CIR dialect attributes into the
+ // LLVM dialect output when there's nothing to translate.
+ if (attr.getName() == func.getExtraAttrsAttrName()) {
+ if (auto extraAttr =
+ mlir::dyn_cast<cir::ExtraFuncAttributesAttr>(attr.getValue());
+ extraAttr && extraAttr.getElements().empty())
+ continue;
+ std::string cirName = "cir." + func.getExtraAttrsAttrName().str();
+ attr.setName(mlir::StringAttr::get(getContext(), cirName));
+ }
result.push_back(attr);
}
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
index 7daeb88ec0900..18125b6a5f213 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
@@ -68,7 +68,18 @@ class CIRDialectLLVMIRTranslationInterface
llvm::ArrayRef<llvm::Instruction *> instructions,
mlir::NamedAttribute attribute,
mlir::LLVM::ModuleTranslation &moduleTranslation) const {
- // TODO(cir): Implement this
+ llvm::Function *llvmFunc = moduleTranslation.lookupFunction(func.getName());
+ llvm::LLVMContext &llvmCtx = moduleTranslation.getLLVMContext();
+ if (auto extraAttr = mlir::dyn_cast<cir::ExtraFuncAttributesAttr>(
+ attribute.getValue())) {
+ for (mlir::NamedAttribute attr : extraAttr.getElements()) {
+ if (auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getValue())) {
+ llvmFunc->addFnAttr(attr.getName().str(), strAttr.getValue().str());
+ }
+ }
+ }
+ // Drop ammended CIR attribute from LLVM op.
+ func->removeAttr(attribute.getName());
}
// Translate CIR's module attributes to LLVM's module metadata
More information about the llvm-branch-commits
mailing list