https://github.com/Men-cotton created 
https://github.com/llvm/llvm-project/pull/219686

Add structured CIR module attributes for OpenCL and C++ for OpenCL language 
versions. Verify their module-level placement and version components so 
lowering can consume explicit source-language version state.

Assisted-by: Codex / GPT-5.6 Sol

>From ac9f57069f82b0e2442ee1ac462e50abb34dde48 Mon Sep 17 00:00:00 2001
From: mencotton <[email protected]>
Date: Mon, 8 Jun 2026 20:56:30 +0900
Subject: [PATCH] [CIR][OpenCL] Add OpenCL language version module attributes

Add structured CIR module attributes for OpenCL and C++ for OpenCL language 
versions. Verify their module-level placement and version components so 
lowering can consume explicit source-language version state.

Assisted-by: Codex / GPT-5.6 Sol
---
 .../clang/CIR/Dialect/IR/CIRDialect.td        |  5 ++
 .../clang/CIR/Dialect/IR/CIROpenCLAttrs.td    | 28 +++++++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 76 +++++++++++++++++++
 clang/lib/CIR/Dialect/IR/CIROpenCLAttrs.cpp   | 15 ++++
 clang/test/CIR/IR/invalid-version.cir         | 73 ++++++++++++++++++
 clang/test/CIR/IR/version.cir                 | 19 +++++
 .../CIR/Transforms/cxx-abi-lowering-attrs.cir |  4 +-
 7 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/IR/invalid-version.cir
 create mode 100644 clang/test/CIR/IR/version.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 135cbdcc7d7be..eb116e030fec5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -25,6 +25,9 @@ def CIR_Dialect : Dialect {
   let cppNamespace = "::cir";
 
   let useDefaultAttributePrinterParser = 1;
+  let hasOperationAttrVerify = 1;
+  let hasRegionArgAttrVerify = 1;
+  let hasRegionResultAttrVerify = 1;
 
   // Enable constant materialization for the CIR dialect. This generates a
   // declaration for the cir::CIRDialect::materializeConstant function. This
@@ -94,6 +97,8 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getAMDGPUXnackAttrName() { return 
"cir.amdgpu_xnack"; }
     static llvm::StringRef getAMDGPUSramEccAttrName() { return 
"cir.amdgpu_sramecc"; }
     static llvm::StringRef getOpenCLKernelArgMetadataAttrName() { return 
"cir.cl.kernel_arg_metadata"; }
+    static llvm::StringRef getOpenCLVersionAttrName() { return 
"cir.cl.version"; }
+    static llvm::StringRef getOpenCLCXXVersionAttrName() { return 
"cir.cl.cxx.version"; }
     static llvm::StringRef getDefaultTlsModelAttrName() { return 
"cir.default_tls_model"; }
 
     void registerAttributes();
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td
index 94b41da4c925d..2a556108c4b9b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROpenCLAttrs.td
@@ -43,4 +43,32 @@ def CIR_OpenCLKernelArgMetadataAttr
   let canHaveIllegalCXXABIType = 0;
 }
 
+//===----------------------------------------------------------------------===//
+// OpenCLVersionAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_OpenCLVersionAttr : CIR_Attr<"OpenCLVersion", "cl.version"> {
+  let summary = "OpenCL version";
+  let description = [{
+    Represents an OpenCL language version preserved as module metadata.
+
+    Example:
+    ```
+    // Module compiled from OpenCL C 1.2.
+    module attributes {cir.cl.version = #cir.cl.version<1, 2>} {}
+    // Module compiled from C++ for OpenCL 2021.
+    module attributes {cir.cl.cxx.version = #cir.cl.version<2021, 0>} {}
+    ```
+  }];
+
+  let parameters = (ins
+    "int32_t":$major,
+    "int32_t":$minor
+  );
+
+  let assemblyFormat = "`<` $major `,` $minor `>`";
+  let genVerifyDecl = 1;
+  let canHaveIllegalCXXABIType = 0;
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIROPENCLATTRS_TD
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8f7bf8062e2e8..b47a424f716ca 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -110,6 +110,82 @@ Operation 
*cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
                                  mlir::cast<mlir::TypedAttr>(value));
 }
 
+static bool isOpenCLVersionAttrName(StringRef attrName) {
+  return attrName == CIRDialect::getOpenCLVersionAttrName() ||
+         attrName == CIRDialect::getOpenCLCXXVersionAttrName();
+}
+
+static LogicalResult verifyOpenCLVersionAttrPlacement(Operation *op,
+                                                      NamedAttribute attr) {
+  StringRef attrName = attr.getName().getValue();
+  if (!isOpenCLVersionAttrName(attrName) || isa<ModuleOp>(op))
+    return success();
+
+  return op->emitError() << attrName
+                         << " attribute must be attached to a module";
+}
+
+static bool areOpenCLVersionsCompatible(cir::OpenCLVersionAttr openCLVersion,
+                                        cir::OpenCLVersionAttr cxxVersion) {
+  return (openCLVersion.getMajor() == 2 && openCLVersion.getMinor() == 0 &&
+          cxxVersion.getMajor() == 1 && cxxVersion.getMinor() == 0) ||
+         (openCLVersion.getMajor() == 3 && openCLVersion.getMinor() == 0 &&
+          cxxVersion.getMajor() == 2021 && cxxVersion.getMinor() == 0);
+}
+
+static LogicalResult verifyOpenCLCXXVersion(ModuleOp module,
+                                            cir::OpenCLVersionAttr cxxVersion) 
{
+  Attribute openCLAttr =
+      module->getAttr(CIRDialect::getOpenCLVersionAttrName());
+  if (!openCLAttr)
+    return module.emitError()
+           << "module attribute '" << CIRDialect::getOpenCLCXXVersionAttrName()
+           << "' requires the companion attribute '"
+           << CIRDialect::getOpenCLVersionAttrName() << "'";
+
+  auto openCLVersion = dyn_cast<cir::OpenCLVersionAttr>(openCLAttr);
+  if (!openCLVersion)
+    return success();
+
+  if (!areOpenCLVersionsCompatible(openCLVersion, cxxVersion))
+    return module.emitError("incompatible OpenCL and C++ for OpenCL versions");
+
+  return success();
+}
+
+LogicalResult cir::CIRDialect::verifyOperationAttribute(Operation *op,
+                                                        NamedAttribute attr) {
+  StringRef attrName = attr.getName().getValue();
+  if (!isOpenCLVersionAttrName(attrName))
+    return success();
+
+  if (failed(verifyOpenCLVersionAttrPlacement(op, attr)))
+    return failure();
+
+  auto version = dyn_cast<cir::OpenCLVersionAttr>(attr.getValue());
+  if (!version) {
+    return op->emitError() << "expected " << attrName
+                           << " to be #cir.cl.version";
+  }
+
+  if (attrName == getOpenCLCXXVersionAttrName())
+    return verifyOpenCLCXXVersion(cast<ModuleOp>(op), version);
+
+  return success();
+}
+
+LogicalResult cir::CIRDialect::verifyRegionArgAttribute(
+    Operation *op, unsigned /*regionIndex*/, unsigned /*argIndex*/,
+    NamedAttribute attr) {
+  return verifyOpenCLVersionAttrPlacement(op, attr);
+}
+
+LogicalResult cir::CIRDialect::verifyRegionResultAttribute(
+    Operation *op, unsigned /*regionIndex*/, unsigned /*resultIndex*/,
+    NamedAttribute attr) {
+  return verifyOpenCLVersionAttrPlacement(op, attr);
+}
+
 
//===----------------------------------------------------------------------===//
 // Helpers
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIROpenCLAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIROpenCLAttrs.cpp
index fac083c3af7a7..ac7e764f01e0f 100644
--- a/clang/lib/CIR/Dialect/IR/CIROpenCLAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIROpenCLAttrs.cpp
@@ -36,3 +36,18 @@ LogicalResult OpenCLKernelArgMetadataAttr::verify(
 
   return success();
 }
+
+//===----------------------------------------------------------------------===//
+// OpenCLVersionAttr definitions
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+OpenCLVersionAttr::verify(function_ref<InFlightDiagnostic()> emitError,
+                          int32_t major, int32_t minor) {
+  if (major <= 0)
+    return emitError() << "OpenCL major version must be positive";
+  if (minor < 0)
+    return emitError() << "OpenCL minor version must be non-negative";
+
+  return success();
+}
diff --git a/clang/test/CIR/IR/invalid-version.cir 
b/clang/test/CIR/IR/invalid-version.cir
new file mode 100644
index 0000000000000..f75c4c6365307
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-version.cir
@@ -0,0 +1,73 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+// expected-error @below {{OpenCL major version must be positive}}
+#attr = #cir.cl.version<-1, 2>
+
+// -----
+
+// expected-error @below {{OpenCL minor version must be non-negative}}
+#attr = #cir.cl.version<3, -1>
+
+// -----
+
+// expected-error @below {{OpenCL major version must be positive}}
+#attr = #cir.cl.version<0, 0>
+
+// -----
+
+// expected-error @below {{expected cir.cl.version to be #cir.cl.version}}
+module attributes {cir.cl.version = "bad"} {
+}
+
+// -----
+
+// expected-error @below {{expected cir.cl.cxx.version to be #cir.cl.version}}
+module attributes {cir.cl.cxx.version = "bad"} {
+}
+
+// -----
+
+// expected-error @below {{module attribute 'cir.cl.cxx.version' requires the 
companion attribute 'cir.cl.version'}}
+module attributes {cir.cl.cxx.version = #cir.cl.version<2021, 0>} {
+}
+
+// -----
+
+// expected-error @below {{incompatible OpenCL and C++ for OpenCL versions}}
+module attributes {
+  cir.cl.cxx.version = #cir.cl.version<2021, 0>,
+  cir.cl.version = #cir.cl.version<2, 0>
+} {
+}
+
+// -----
+
+module {
+  // expected-error @below {{cir.cl.version attribute must be attached to a 
module}}
+  cir.func @not_module_attr() attributes {cir.cl.version = #cir.cl.version<1, 
2>} {
+    cir.return
+  }
+}
+
+// -----
+
+module {
+  // expected-error @below {{cir.cl.cxx.version attribute must be attached to 
a module}}
+  cir.func @not_module_attr() attributes {cir.cl.cxx.version = 
#cir.cl.version<2021, 0>} {
+    cir.return
+  }
+}
+
+// -----
+
+module {
+  // expected-error @below {{cir.cl.version attribute must be attached to a 
module}}
+  cir.func private @not_module_arg(!cir.int<s, 32> {cir.cl.version = 
#cir.cl.version<1, 2>})
+}
+
+// -----
+
+module {
+  // expected-error @below {{cir.cl.cxx.version attribute must be attached to 
a module}}
+  cir.func private @not_module_cxx_result() -> (!cir.int<s, 32> 
{cir.cl.cxx.version = #cir.cl.version<2021, 0>})
+}
diff --git a/clang/test/CIR/IR/version.cir b/clang/test/CIR/IR/version.cir
new file mode 100644
index 0000000000000..47603a8dff658
--- /dev/null
+++ b/clang/test/CIR/IR/version.cir
@@ -0,0 +1,19 @@
+// RUN: cir-opt %s -split-input-file --verify-roundtrip | FileCheck %s
+
+// CHECK: module attributes {cir.cl.version = #cir.cl.version<1, 2>}
+module attributes {cir.cl.version = #cir.cl.version<1, 2>} { }
+
+// -----
+
+// CHECK: module attributes {cir.cl.version = #cir.cl.version<3, 0>}
+module attributes {cir.cl.version = #cir.cl.version<3, 0>} { }
+
+// -----
+
+// CHECK: module attributes {cir.cl.cxx.version = #cir.cl.version<1, 0>, 
cir.cl.version = #cir.cl.version<2, 0>}
+module attributes {cir.cl.cxx.version = #cir.cl.version<1, 0>, cir.cl.version 
= #cir.cl.version<2, 0>} { }
+
+// -----
+
+// CHECK: module attributes {cir.cl.cxx.version = #cir.cl.version<2021, 0>, 
cir.cl.version = #cir.cl.version<3, 0>}
+module attributes {cir.cl.cxx.version = #cir.cl.version<2021, 0>, 
cir.cl.version = #cir.cl.version<3, 0>} { }
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-attrs.cir 
b/clang/test/CIR/Transforms/cxx-abi-lowering-attrs.cir
index 569b1f6a87ab1..06259eda595a1 100644
--- a/clang/test/CIR/Transforms/cxx-abi-lowering-attrs.cir
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-attrs.cir
@@ -44,7 +44,9 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
     // Attrs don't really allow getting a 'bad' type into them.  We attempt to
     // transform them anyway, but they'll probably never fail the legalizer.
 
-    cir.trap
+    // OpenCLVersionAttr contains no types and remains unchanged.
+    cir.trap {test.opencl_versions = [#cir.cl.version<3, 0>]}
+    // CHECK: cir.trap {test.opencl_versions = [#cir.cl.version<3, 0>]}
   }
 
   // cir::TypeAttr: function type is a type attr, so this shows it converting.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to