[clang] [CIR] Add calling_conv attribute to FuncOp with lowering support (PR #189345)
Rana Pratap Reddy via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 13 22:47:43 PDT 2026
https://github.com/ranapratap55 updated https://github.com/llvm/llvm-project/pull/189345
>From d3f369ec233566a67dcb49c795ddf5d93787ce2e Mon Sep 17 00:00:00 2001
From: ranapratap55 <RanaPratapReddy.Nimmakayala at amd.com>
Date: Thu, 26 Mar 2026 15:31:43 +0530
Subject: [PATCH 1/4] [CIR] Add calling convention values to CIR_CallingConv
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index b806800275c7b..5fd8a35c5fcb7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3611,9 +3611,14 @@ def CIR_OptionalPriorityAttr : OptionalAttr<
>
>;
-// TODO(CIR): CallingConv is a placeholder here so we can use it in
-// infrastructure calls, but it currently has no values.
-def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", []>;
+def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [
+ I32EnumAttrCase<"C", 1, "c">,
+ I32EnumAttrCase<"SpirKernel", 2, "spir_kernel">,
+ I32EnumAttrCase<"SpirFunction", 3, "spir_function">,
+ I32EnumAttrCase<"OpenCLKernel", 4, "opencl_kernel">,
+ I32EnumAttrCase<"PTXKernel", 5, "ptx_kernel">,
+ I32EnumAttrCase<"AMDGPUKernel", 6, "amdgpu_kernel">
+]>;
def CIR_FuncOp : CIR_Op<"func", [
AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface,
>From c7a63b2087bf736835b8b5d0aaa6bc405cc15429 Mon Sep 17 00:00:00 2001
From: ranapratap55 <RanaPratapReddy.Nimmakayala at amd.com>
Date: Mon, 30 Mar 2026 14:54:22 +0530
Subject: [PATCH 2/4] [CIR] Add calling_conv attribute to FuncOp with lowering
support
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 17 ++++++++-
clang/include/clang/CIR/MissingFeatures.h | 1 -
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 4 +-
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 6 +--
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 11 +++---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 27 ++++++++++++-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 29 +++++++++++---
clang/test/CIR/IR/calling-conv.cir | 38 +++++++++++++++++++
clang/test/CIR/Lowering/calling-conv.cir | 34 +++++++++++++++++
9 files changed, 146 insertions(+), 21 deletions(-)
create mode 100644 clang/test/CIR/IR/calling-conv.cir
create mode 100644 clang/test/CIR/Lowering/calling-conv.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5fd8a35c5fcb7..4b00bd1ed4153 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3611,6 +3611,8 @@ def CIR_OptionalPriorityAttr : OptionalAttr<
>
>;
+// The enumeration values are not necessarily in sync with `clang::CallingConv`
+// or `llvm::CallingConv`.
def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [
I32EnumAttrCase<"C", 1, "c">,
I32EnumAttrCase<"SpirKernel", 2, "spir_kernel">,
@@ -3634,6 +3636,11 @@ def CIR_FuncOp : CIR_Op<"func", [
The function linkage information is specified by `linkage`, as defined by
`GlobalLinkageKind` attribute.
+ The `calling_conv` attribute specifies the calling convention of the function.
+ By default calling convention is `CallingConv::C`. When printed, C calling
+ convention is omitted. Other calling conventions are printed as `cc(<mnemonic>)`,
+ e.g. `cc(amdgpu_kernel)`.
+
A compiler builtin function must be marked as `builtin` for further
processing when lowering from CIR.
@@ -3675,6 +3682,9 @@ def CIR_FuncOp : CIR_Op<"func", [
// Linkage information
cir.func linkonce_odr @some_method(...)
+ // Calling convention information
+ cir.func @func1(...) cc(amdgpu_kernel)
+
// Inline information
cir.func no_inline @some_method(...)
@@ -3706,6 +3716,10 @@ def CIR_FuncOp : CIR_Op<"func", [
CIR_GlobalLinkageKind,
"cir::GlobalLinkageKind::ExternalLinkage"
>:$linkage,
+ DefaultValuedAttr<
+ CIR_CallingConv,
+ "cir::CallingConv::C"
+ >:$calling_conv,
OptionalAttr<StrAttr>:$sym_visibility,
UnitAttr:$comdat,
OptionalAttr<DictArrayAttr>:$arg_attrs,
@@ -3724,7 +3738,8 @@ def CIR_FuncOp : CIR_Op<"func", [
let builders = [OpBuilder<(ins
"llvm::StringRef":$sym_name, "FuncType":$type,
- CArg<"cir::GlobalLinkageKind", "cir::GlobalLinkageKind::ExternalLinkage">:$linkage)
+ CArg<"cir::GlobalLinkageKind", "cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
+ CArg<"cir::CallingConv", "cir::CallingConv::C">:$callingConv)
>];
let extraClassDeclaration = [{
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index ac02433fb504a..086e1dcef524a 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -71,7 +71,6 @@ struct MissingFeatures {
static bool opFuncArmNewAttr() { return false; }
static bool opFuncArmStreamingAttr() { return false; }
static bool opFuncAstDeclAttr() { return false; }
- static bool opFuncCallingConv() { return false; }
static bool opFuncColdHotAttr() { return false; }
static bool opFuncCPUAndFeaturesAttributes() { return false; }
static bool opFuncExceptions() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index ccf49c6c76d66..f75b54b2050c1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1285,8 +1285,8 @@ mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
cir::FuncOp callee,
ArrayRef<mlir::Value> args,
mlir::NamedAttrList attrs) {
- // TODO(cir): set the calling convention to this runtime call.
- assert(!cir::MissingFeatures::opFuncCallingConv());
+
+ // TODO(cir): set the calling convention of the runtime function.
cir::CallOp call = builder.createCallOp(loc, callee, args);
assert(call->getNumResults() <= 1 &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 75658b23790bf..32988b81c5a2b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -2084,7 +2084,6 @@ static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
// Prototype: void __cxa_bad_cast();
// TODO(cir): set the calling convention of the runtime function.
- assert(!cir::MissingFeatures::opFuncCallingConv());
cir::FuncType fnTy =
cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
@@ -2092,8 +2091,7 @@ static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
}
static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) {
- // TODO(cir): set the calling convention to the runtime function.
- assert(!cir::MissingFeatures::opFuncCallingConv());
+ // TODO(cir): set the calling convention of the runtime function.
cgf.emitRuntimeCall(loc, getBadCastFn(cgf));
cir::UnreachableOp::create(cgf.getBuilder(), loc);
@@ -2173,8 +2171,6 @@ static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
assert(!cir::MissingFeatures::opFuncReadOnly());
// TODO(cir): set the calling convention of the runtime function.
- assert(!cir::MissingFeatures::opFuncCallingConv());
-
cir::FuncType FTy = cgf.getBuilder().getFuncType(
{voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);
cir::FuncOp fn = cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 2f64fe45a694d..04148df59889d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2660,11 +2660,9 @@ void CIRGenModule::setCIRFunctionAttributes(GlobalDecl globalDecl,
// TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
- // TODO(cir): typically the calling conv is set right here, but since
- // cir::CallingConv is empty and we've not yet added calling-conv to FuncOop,
- // this isn't really useful here. This should call func.setCallingConv/etc
- // later.
- assert(!cir::MissingFeatures::opFuncCallingConv());
+ // TODO(cir): Apply the calling convention computed by constructAttributeList
+ // to the function. Requires CodeGen target wiring (e.g., AMDGPU sets
+ // AMDGPUKernel). See CIRGenModule::setCIRFunctionAttributes in OG.
}
void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,
@@ -3108,7 +3106,8 @@ cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
if (entry) {
// TODO(cir): set the attributes of the function.
assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
- assert(!cir::MissingFeatures::opFuncCallingConv());
+ // TODO(cir): Set the calling convention on runtime functions if needed.
+ // Runtime functions typically use CallingConv::C (the default).
setWindowsItaniumDLLImport(*this, isLocal, entry, name);
entry.setDSOLocal(true);
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d685a14ef263a..fd011bfec41f9 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -138,6 +138,7 @@ template <typename Ty> struct EnumTraits {};
REGISTER_ENUM_TYPE(GlobalLinkageKind);
REGISTER_ENUM_TYPE(VisibilityKind);
REGISTER_ENUM_TYPE(SideEffect);
+REGISTER_ENUM_TYPE(CallingConv);
} // namespace
/// Parse an enum from the keyword, or default to the provided default value.
@@ -2129,7 +2130,7 @@ static llvm::StringRef getLinkageAttrNameString() { return "linkage"; }
void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
StringRef name, FuncType type,
- GlobalLinkageKind linkage) {
+ GlobalLinkageKind linkage, CallingConv callingConv) {
result.addRegion();
result.addAttribute(SymbolTable::getSymbolAttrName(),
builder.getStringAttr(name));
@@ -2138,6 +2139,10 @@ void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
result.addAttribute(
getLinkageAttrNameString(),
GlobalLinkageKindAttr::get(builder.getContext(), linkage));
+ result.addAttribute(getCallingConvAttrName(result.name),
+ CallingConvAttr::get(builder.getContext(), callingConv));
+ result.addAttribute(getGlobalVisibilityAttrName(result.name),
+ cir::VisibilityAttr::get(builder.getContext()));
}
ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
@@ -2272,6 +2277,20 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
return failure();
}
+ // Default to C calling convention if no keyword is provided.
+ mlir::StringAttr callConvNameAttr = getCallingConvAttrName(state.name);
+ cir::CallingConv callConv = cir::CallingConv::C;
+ if (parser.parseOptionalKeyword("cc").succeeded()) {
+ if (parser.parseLParen().failed())
+ return failure();
+ if (parseCIRKeyword<cir::CallingConv>(parser, callConv).failed())
+ return parser.emitError(loc) << "unknown calling convention";
+ if (parser.parseRParen().failed())
+ return failure();
+ }
+ state.addAttribute(callConvNameAttr,
+ cir::CallingConvAttr::get(parser.getContext(), callConv));
+
auto parseGlobalDtorCtor =
[&](StringRef keyword,
llvm::function_ref<void(std::optional<int> prio)> createAttr)
@@ -2483,6 +2502,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p << ")";
}
+ if (getCallingConv() != cir::CallingConv::C) {
+ p << " cc(";
+ p << stringifyCallingConv(getCallingConv());
+ p << ")";
+ }
+
if (std::optional<StringRef> personalityName = getPersonality()) {
p << " personality(";
p.printSymbolName(*personalityName);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c352ef91d1ee2..eb4f9b3a501fb 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -183,6 +183,27 @@ mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage) {
llvm_unreachable("Unknown CIR linkage type");
}
+static mlir::LLVM::CConv convertCallingConv(cir::CallingConv callingConv) {
+ using CIR = cir::CallingConv;
+ using LLVM = mlir::LLVM::CConv;
+
+ switch (callingConv) {
+ case CIR::C:
+ return LLVM::C;
+ case CIR::SpirKernel:
+ return LLVM::SPIR_KERNEL;
+ case CIR::SpirFunction:
+ return LLVM::SPIR_FUNC;
+ case CIR::OpenCLKernel:
+ llvm_unreachable("NYI");
+ case CIR::PTXKernel:
+ return LLVM::PTX_Kernel;
+ case CIR::AMDGPUKernel:
+ return LLVM::AMDGPU_KERNEL;
+ }
+ llvm_unreachable("Unknown calling convention");
+}
+
mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
cir::CopyOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
@@ -1658,7 +1679,6 @@ mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite(
static void lowerCallAttributes(cir::CIRCallOpInterface op,
SmallVectorImpl<mlir::NamedAttribute> &result) {
for (mlir::NamedAttribute attr : op->getAttrs()) {
- assert(!cir::MissingFeatures::opFuncCallingConv());
if (attr.getName() == CIRDialect::getCalleeAttrName() ||
attr.getName() == CIRDialect::getSideEffectAttrName() ||
attr.getName() == CIRDialect::getNoThrowAttrName() ||
@@ -2146,12 +2166,12 @@ mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
cir::FuncOp func, bool filterArgAndResAttrs,
SmallVectorImpl<mlir::NamedAttribute> &result) const {
- assert(!cir::MissingFeatures::opFuncCallingConv());
for (mlir::NamedAttribute attr : func->getAttrs()) {
- assert(!cir::MissingFeatures::opFuncCallingConv());
if (attr.getName() == mlir::SymbolTable::getSymbolAttrName() ||
attr.getName() == func.getFunctionTypeAttrName() ||
attr.getName() == getLinkageAttrNameString() ||
+ attr.getName() == func.getCallingConvAttrName() ||
+ attr.getName() == func.getGlobalVisibilityAttrName() ||
attr.getName() == func.getDsoLocalAttrName() ||
attr.getName() == func.getInlineKindAttrName() ||
attr.getName() == func.getSideEffectAttrName() ||
@@ -2229,8 +2249,7 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
"expected single location or unknown location here");
mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage());
- assert(!cir::MissingFeatures::opFuncCallingConv());
- mlir::LLVM::CConv cconv = mlir::LLVM::CConv::C;
+ mlir::LLVM::CConv cconv = convertCallingConv(op.getCallingConv());
SmallVector<mlir::NamedAttribute, 4> attributes;
lowerFuncAttributes(op, /*filterArgAndResAttrs=*/false, attributes);
diff --git a/clang/test/CIR/IR/calling-conv.cir b/clang/test/CIR/IR/calling-conv.cir
new file mode 100644
index 0000000000000..3f191aa647206
--- /dev/null
+++ b/clang/test/CIR/IR/calling-conv.cir
@@ -0,0 +1,38 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module {
+ // CHECK: cir.func @default_cc(%arg0: !s32i) -> !s32i
+ cir.func @default_cc(%arg0: !s32i) -> !s32i {
+ cir.return %arg0 : !s32i
+ }
+
+ // CHECK: cir.func @amdgpu_kernel_func() cc(amdgpu_kernel)
+ cir.func @amdgpu_kernel_func() cc(amdgpu_kernel) {
+ cir.return
+ }
+
+ // CHECK: cir.func @spir_kernel_func() cc(spir_kernel)
+ cir.func @spir_kernel_func() cc(spir_kernel) {
+ cir.return
+ }
+
+ // CHECK: cir.func @spir_function_func() cc(spir_function)
+ cir.func @spir_function_func() cc(spir_function) {
+ cir.return
+ }
+
+ // CHECK: cir.func @ptx_kernel_func() cc(ptx_kernel)
+ cir.func @ptx_kernel_func() cc(ptx_kernel) {
+ cir.return
+ }
+
+ // CHECK: cir.func no_inline dso_local @amdgpu_noinline() cc(amdgpu_kernel)
+ cir.func no_inline dso_local @amdgpu_noinline() cc(amdgpu_kernel) {
+ cir.return
+ }
+
+ // CHECK: cir.func private @amdgpu_decl() cc(amdgpu_kernel)
+ cir.func private @amdgpu_decl() cc(amdgpu_kernel)
+}
diff --git a/clang/test/CIR/Lowering/calling-conv.cir b/clang/test/CIR/Lowering/calling-conv.cir
new file mode 100644
index 0000000000000..092050e83780d
--- /dev/null
+++ b/clang/test/CIR/Lowering/calling-conv.cir
@@ -0,0 +1,34 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s -check-prefix=MLIR
+// RUN: cir-translate %s -cir-to-llvmir --disable-cc-lowering | FileCheck %s -check-prefix=LLVM
+
+module {
+ // MLIR: llvm.func @default_cc()
+ // LLVM: define void @default_cc()
+ cir.func @default_cc() {
+ cir.return
+ }
+
+ // MLIR: llvm.func amdgpu_kernelcc @amdgpu_kernel_func()
+ // LLVM: define amdgpu_kernel void @amdgpu_kernel_func()
+ cir.func @amdgpu_kernel_func() cc(amdgpu_kernel) {
+ cir.return
+ }
+
+ // MLIR: llvm.func spir_kernelcc @spir_kernel_func()
+ // LLVM: define spir_kernel void @spir_kernel_func()
+ cir.func @spir_kernel_func() cc(spir_kernel) {
+ cir.return
+ }
+
+ // MLIR: llvm.func spir_funccc @spir_function_func()
+ // LLVM: define spir_func void @spir_function_func()
+ cir.func @spir_function_func() cc(spir_function) {
+ cir.return
+ }
+
+ // MLIR: llvm.func ptx_kernelcc @ptx_kernel_func()
+ // LLVM: define ptx_kernel void @ptx_kernel_func()
+ cir.func @ptx_kernel_func() cc(ptx_kernel) {
+ cir.return
+ }
+}
>From 6f8ba7929a36a91d81e7be3b5e26286d43f7687b Mon Sep 17 00:00:00 2001
From: ranapratap55 <RanaPratapReddy.Nimmakayala at amd.com>
Date: Tue, 31 Mar 2026 22:21:28 +0530
Subject: [PATCH 3/4] [CIR] Restore MissingFeatures asserts and fix
OpenCLKernel handling
---
clang/include/clang/CIR/MissingFeatures.h | 2 ++
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 3 ++-
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 6 +++++-
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 11 ++++++-----
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 +++-
5 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 086e1dcef524a..199143d12d53a 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -75,6 +75,8 @@ struct MissingFeatures {
static bool opFuncCPUAndFeaturesAttributes() { return false; }
static bool opFuncExceptions() { return false; }
static bool opFuncExtraAttrs() { return false; }
+ static bool opFuncCallingConv() { return false; }
+ static bool callConvOpenCLKernel() { return false; }
static bool opFuncMaybeHandleStaticInExternC() { return false; }
static bool opFuncMinSizeAttr() { return false; }
static bool opFuncMultipleReturnVals() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index f75b54b2050c1..909e491d392a3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1286,7 +1286,8 @@ mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
ArrayRef<mlir::Value> args,
mlir::NamedAttrList attrs) {
- // TODO(cir): set the calling convention of the runtime function.
+ // TODO(cir): set the calling convention to this runtime call.
+ assert(!cir::MissingFeatures::opFuncCallingConv());
cir::CallOp call = builder.createCallOp(loc, callee, args);
assert(call->getNumResults() <= 1 &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 32988b81c5a2b..75658b23790bf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -2084,6 +2084,7 @@ static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
// Prototype: void __cxa_bad_cast();
// TODO(cir): set the calling convention of the runtime function.
+ assert(!cir::MissingFeatures::opFuncCallingConv());
cir::FuncType fnTy =
cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
@@ -2091,7 +2092,8 @@ static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
}
static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) {
- // TODO(cir): set the calling convention of the runtime function.
+ // TODO(cir): set the calling convention to the runtime function.
+ assert(!cir::MissingFeatures::opFuncCallingConv());
cgf.emitRuntimeCall(loc, getBadCastFn(cgf));
cir::UnreachableOp::create(cgf.getBuilder(), loc);
@@ -2171,6 +2173,8 @@ static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
assert(!cir::MissingFeatures::opFuncReadOnly());
// TODO(cir): set the calling convention of the runtime function.
+ assert(!cir::MissingFeatures::opFuncCallingConv());
+
cir::FuncType FTy = cgf.getBuilder().getFuncType(
{voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);
cir::FuncOp fn = cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 04148df59889d..e11cc6050381f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2660,9 +2660,11 @@ void CIRGenModule::setCIRFunctionAttributes(GlobalDecl globalDecl,
// TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
- // TODO(cir): Apply the calling convention computed by constructAttributeList
- // to the function. Requires CodeGen target wiring (e.g., AMDGPU sets
- // AMDGPUKernel). See CIRGenModule::setCIRFunctionAttributes in OG.
+ // TODO(cir): Set the calling convention computed by constructAttributeList
+ // on the function. FuncOp supports calling_conv, but target-specific
+ // CodeGen is needed to set it correctly (e.g., AMDGPU kernel functions
+ // should be marked with AMDGPUKernel).
+ assert(!cir::MissingFeatures::opFuncCallingConv());
}
void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,
@@ -3106,8 +3108,7 @@ cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
if (entry) {
// TODO(cir): set the attributes of the function.
assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
- // TODO(cir): Set the calling convention on runtime functions if needed.
- // Runtime functions typically use CallingConv::C (the default).
+ assert(!cir::MissingFeatures::opFuncCallingConv());
setWindowsItaniumDLLImport(*this, isLocal, entry, name);
entry.setDSOLocal(true);
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index eb4f9b3a501fb..d91f2abba87d8 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -195,7 +195,9 @@ static mlir::LLVM::CConv convertCallingConv(cir::CallingConv callingConv) {
case CIR::SpirFunction:
return LLVM::SPIR_FUNC;
case CIR::OpenCLKernel:
- llvm_unreachable("NYI");
+ assert(!cir::MissingFeatures::callConvOpenCLKernel());
+ llvm_unreachable(
+ "OpenCLKernel must be resolved to target-specific CC in CodeGen");
case CIR::PTXKernel:
return LLVM::PTX_Kernel;
case CIR::AMDGPUKernel:
>From 13060e169edc892983134c0c55aac9e7c33b9579 Mon Sep 17 00:00:00 2001
From: ranapratap55 <RanaPratapReddy.Nimmakayala at amd.com>
Date: Fri, 3 Apr 2026 12:13:26 +0530
Subject: [PATCH 4/4] [CIR] Remove OpenCLKernel enum and updated the ordering
to match llvm::CallingConv
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 16 ++++++++--------
clang/include/clang/CIR/MissingFeatures.h | 1 -
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ----
3 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4b00bd1ed4153..32c7311bc2144 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3611,15 +3611,15 @@ def CIR_OptionalPriorityAttr : OptionalAttr<
>
>;
-// The enumeration values are not necessarily in sync with `clang::CallingConv`
-// or `llvm::CallingConv`.
+// The enumeration cases are ordered to match `llvm::CallingConv`. The values
+// are CIR-specific and are not in sync with `llvm::CallingConv` or
+// `clang::CallingConv`.
def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [
- I32EnumAttrCase<"C", 1, "c">,
- I32EnumAttrCase<"SpirKernel", 2, "spir_kernel">,
- I32EnumAttrCase<"SpirFunction", 3, "spir_function">,
- I32EnumAttrCase<"OpenCLKernel", 4, "opencl_kernel">,
- I32EnumAttrCase<"PTXKernel", 5, "ptx_kernel">,
- I32EnumAttrCase<"AMDGPUKernel", 6, "amdgpu_kernel">
+ I32EnumAttrCase<"C", 0, "c">,
+ I32EnumAttrCase<"PTXKernel", 1, "ptx_kernel">,
+ I32EnumAttrCase<"SpirFunction", 2, "spir_function">,
+ I32EnumAttrCase<"SpirKernel", 3, "spir_kernel">,
+ I32EnumAttrCase<"AMDGPUKernel", 4, "amdgpu_kernel">
]>;
def CIR_FuncOp : CIR_Op<"func", [
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 199143d12d53a..3a4cb1a16a696 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -76,7 +76,6 @@ struct MissingFeatures {
static bool opFuncExceptions() { return false; }
static bool opFuncExtraAttrs() { return false; }
static bool opFuncCallingConv() { return false; }
- static bool callConvOpenCLKernel() { return false; }
static bool opFuncMaybeHandleStaticInExternC() { return false; }
static bool opFuncMinSizeAttr() { return false; }
static bool opFuncMultipleReturnVals() { return false; }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index d91f2abba87d8..216b4e611f8e4 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -194,10 +194,6 @@ static mlir::LLVM::CConv convertCallingConv(cir::CallingConv callingConv) {
return LLVM::SPIR_KERNEL;
case CIR::SpirFunction:
return LLVM::SPIR_FUNC;
- case CIR::OpenCLKernel:
- assert(!cir::MissingFeatures::callConvOpenCLKernel());
- llvm_unreachable(
- "OpenCLKernel must be resolved to target-specific CC in CodeGen");
case CIR::PTXKernel:
return LLVM::PTX_Kernel;
case CIR::AMDGPUKernel:
More information about the cfe-commits
mailing list