[Mlir-commits] [mlir] Add`final` specifier to the classop (PR #145977)

Jaden Angella llvmlistbot at llvm.org
Thu Jun 26 14:48:04 PDT 2025


https://github.com/Jaddyen created https://github.com/llvm/llvm-project/pull/145977

In some use cases of the `ClassOp`, eg MLGO, we would like to be able to declare the class as final. This specifier allows for that.

>From b8c7b180932c0a8e0e2b0bb5f6e2aecbd4b1f11b Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Thu, 26 Jun 2025 21:45:51 +0000
Subject: [PATCH] Add final specifier to the classop

---
 mlir/include/mlir/Dialect/EmitC/IR/EmitC.td  | 15 +++++++++++++--
 mlir/lib/Target/Cpp/TranslateToCpp.cpp       |  6 ++++--
 mlir/test/mlir-translate/emitc_classops.mlir |  4 ++--
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 91ee89919e58e..7fe2da8f7e044 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1618,10 +1618,20 @@ def EmitC_ClassOp
         return
       }
     }
+    // Class with a final speciferAdd commentMore actions
+    emitc.class final @modelClass {
+      emitc.field @fieldName0 : !emitc.array<1xf32> = {emitc.opaque = "input_tensor"}
+      emitc.func @execute() {
+        %0 = "emitc.constant"() <{value = 0 : index}> : () -> !emitc.size_t
+        %1 = get_field @fieldName0 : !emitc.array<1xf32>
+        %2 = subscript %1[%0] : (!emitc.array<1xf32>, !emitc.size_t) -> !emitc.lvalue<f32>
+        return
+      }
+    }
     ```
   }];
 
-  let arguments = (ins SymbolNameAttr:$sym_name);
+  let arguments = (ins SymbolNameAttr:$sym_name, UnitAttr:$final_specifier);
 
   let regions = (region AnyRegion:$body);
 
@@ -1632,7 +1642,8 @@ def EmitC_ClassOp
 
   let hasCustomAssemblyFormat = 1;
 
-  let assemblyFormat = [{ $sym_name attr-dict-with-keyword $body }];
+  let assemblyFormat =
+      [{ (`final` $final_specifier^)? $sym_name attr-dict-with-keyword $body }];
 }
 
 def EmitC_FieldOp : EmitC_Op<"field", [Symbol]> {
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index c04548688bcf6..a4696568f69bd 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -1000,8 +1000,10 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
 static LogicalResult printOperation(CppEmitter &emitter, ClassOp classOp) {
   CppEmitter::Scope classScope(emitter);
   raw_indented_ostream &os = emitter.ostream();
-  os << "class " << classOp.getSymName() << " {\n";
-  os << "public:\n";
+  os << "class " << classOp.getSymName();
+  if (classOp.getFinalSpecifier())
+    os << " final ";
+  os << "{\n public:\n";
   os.indent();
 
   for (Operation &op : classOp) {
diff --git a/mlir/test/mlir-translate/emitc_classops.mlir b/mlir/test/mlir-translate/emitc_classops.mlir
index e42844412860e..8f81452629f11 100644
--- a/mlir/test/mlir-translate/emitc_classops.mlir
+++ b/mlir/test/mlir-translate/emitc_classops.mlir
@@ -1,6 +1,6 @@
 // RUN: mlir-translate --mlir-to-cpp %s | FileCheck %s
 
-emitc.class @modelClass {
+emitc.class final @modelClass {
     emitc.field @fieldName0 : !emitc.array<1xf32> 
     emitc.field @fieldName1 : !emitc.array<1xf32> 
     emitc.func @execute() {
@@ -12,7 +12,7 @@ emitc.class @modelClass {
     }
 }
 
-// CHECK: class modelClass {
+// CHECK: class modelClass final {
 // CHECK-NEXT: public:
 // CHECK-NEXT:  float[1] fieldName0;
 // CHECK-NEXT:  float[1] fieldName1;



More information about the Mlir-commits mailing list