From 22db8d56e02e5e87a1ca8d2f474a39bb02dba62d Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Thu, 23 Apr 2026 01:56:12 -0700 Subject: [PATCH 1/3] [OM] Simplify ObjectFieldOp to use StringAttr instead of symbol array Replace FlatSymbolRefArrayAttr with StringAttr for field names, changing syntax from 'object, [@field]' to 'object["field"]'. Nested field access now requires chaining ObjectFieldOp instead of using an array path. This moves verification from the VerifyObjectFields pass into the ObjectFieldOp verifier itself by adding SymbolUserOpInterface, eliminating the need for a separate pass. The Evaluator is updated to handle StringAttr and dereference ReferenceValue. --- include/circt/Dialect/OM/OMOps.td | 9 +- include/circt/Dialect/OM/OMPasses.td | 7 - .../Bindings/Python/dialects/om.py | 10 +- .../FIRRTL/Transforms/LowerClasses.cpp | 13 +- lib/Dialect/OM/Evaluator/Evaluator.cpp | 30 ++-- lib/Dialect/OM/OMOps.cpp | 33 +++++ lib/Dialect/OM/OMReductions.cpp | 6 +- lib/Dialect/OM/Transforms/CMakeLists.txt | 1 - lib/Dialect/OM/Transforms/FreezePaths.cpp | 2 +- .../OM/Transforms/VerifyObjectFields.cpp | 137 ------------------ lib/Firtool/Firtool.cpp | 10 -- test/Dialect/FIRRTL/lower-classes.mlir | 10 +- .../OM/Reduction/class-field-pruner.mlir | 4 +- test/Dialect/OM/errors.mlir | 26 +--- test/Dialect/OM/freeze-paths.mlir | 10 +- test/Dialect/OM/link-modules.mlir | 8 +- test/Dialect/OM/round-trip.mlir | 20 +-- .../Dialect/OM/Evaluator/EvaluatorTests.cpp | 62 ++++---- 18 files changed, 130 insertions(+), 268 deletions(-) delete mode 100644 lib/Dialect/OM/Transforms/VerifyObjectFields.cpp diff --git a/include/circt/Dialect/OM/OMOps.td b/include/circt/Dialect/OM/OMOps.td index 01e4dd315edd..36b4b4f66777 100644 --- a/include/circt/Dialect/OM/OMOps.td +++ b/include/circt/Dialect/OM/OMOps.td @@ -206,10 +206,13 @@ def ObjectOp : OMOp<"object", [ }]; } -def ObjectFieldOp : OMOp<"object.field", [Pure]> { +def ObjectFieldOp : OMOp<"object.field", [ + Pure, + DeclareOpInterfaceMethods + ]> { let arguments = (ins ClassType:$object, - FlatSymbolRefArrayAttr:$fieldPath + StrAttr:$field ); let results = (outs @@ -217,7 +220,7 @@ def ObjectFieldOp : OMOp<"object.field", [Pure]> { ); let assemblyFormat = [{ - $object `,` $fieldPath attr-dict `:` functional-type($object, $result) + $object `[` $field `]` attr-dict `:` functional-type($object, $result) }]; } diff --git a/include/circt/Dialect/OM/OMPasses.td b/include/circt/Dialect/OM/OMPasses.td index 2380601fa538..982298a0360c 100644 --- a/include/circt/Dialect/OM/OMPasses.td +++ b/include/circt/Dialect/OM/OMPasses.td @@ -25,13 +25,6 @@ def LinkModules: Pass<"om-link-modules", "mlir::ModuleOp"> { }]; } -def VerifyObjectFields: Pass<"om-verify-object-fields"> { - let summary = "Verify fields of ObjectOp are valid"; - let description = [{ - Verify object fields are valid. - }]; -} - def StripOMPass : Pass<"strip-om", "mlir::ModuleOp"> { let summary = "Remove OM information"; let description = [{ diff --git a/integration_test/Bindings/Python/dialects/om.py b/integration_test/Bindings/Python/dialects/om.py index 7162d2b9e4c4..66da2db607bc 100644 --- a/integration_test/Bindings/Python/dialects/om.py +++ b/integration_test/Bindings/Python/dialects/om.py @@ -88,10 +88,10 @@ om.class @IntegerBinaryArithmeticObjectsDelayed() -> (result: !om.integer) { %0 = om.object @Class1(%5) : (!om.integer) -> !om.class.type<@Class1> - %1 = om.object.field %0, [@value] : (!om.class.type<@Class1>) -> !om.integer + %1 = om.object.field %0["value"] : (!om.class.type<@Class1>) -> !om.integer %2 = om.object @Class2() : () -> !om.class.type<@Class2> - %3 = om.object.field %2, [@value] : (!om.class.type<@Class2>) -> !om.integer + %3 = om.object.field %2["value"] : (!om.class.type<@Class2>) -> !om.integer %5 = om.integer.add %1, %3 : !om.integer om.class.fields %5 : !om.integer @@ -152,13 +152,13 @@ print(obj.reference) for (name, field) in obj: - # location from om.class.field @child, %0 : !om.class.type<@Child> + # location from om.class.field "child" # CHECK: name: child, field: (result.getType())) continue; - // The path to the field is just this output's name. - auto objectFieldPath = builder.getArrayAttr({FlatSymbolRefAttr::get( - firrtlInstance.getPortNameAttr(result.getResultNumber()))}); - // Create the field access. auto objectField = om::ObjectFieldOp::create( - builder, object.getLoc(), result.getType(), object, objectFieldPath); + builder, object.getLoc(), result.getType(), object, + firrtlInstance.getPortNameAttr(result.getResultNumber())); result.replaceAllUsesWith(objectField); } @@ -1958,11 +1955,9 @@ struct ObjectSubfieldOpConversion if (element.direction == Direction::In) return failure(); - auto field = FlatSymbolRefAttr::get(element.name); - auto path = rewriter.getArrayAttr({field}); auto type = typeConverter->convertType(element.type); rewriter.replaceOpWithNewOp(op, type, adaptor.getInput(), - path); + element.name); return success(); } @@ -2058,7 +2053,7 @@ struct ObjectFieldOpConversion : public OpConversionPattern { return failure(); rewriter.replaceOpWithNewOp( - op, type, adaptor.getObject(), adaptor.getFieldPathAttr()); + op, type, adaptor.getObject(), adaptor.getFieldAttr()); return success(); } diff --git a/lib/Dialect/OM/Evaluator/Evaluator.cpp b/lib/Dialect/OM/Evaluator/Evaluator.cpp index e328dc8f7a18..ccf8bbad1d09 100644 --- a/lib/Dialect/OM/Evaluator/Evaluator.cpp +++ b/lib/Dialect/OM/Evaluator/Evaluator.cpp @@ -744,22 +744,24 @@ circt::om::Evaluator::evaluateObjectField(ObjectFieldOp op, return objectFieldValue; } + // If the result is a ReferenceValue, dereference it to get the actual object. + if (auto *ref = llvm::dyn_cast(result.get())) { + auto stripped = ref->getStrippedValue(); + if (failed(stripped)) + return failure(); + result = stripped.value(); + } + auto *currentObject = llvm::cast(result.get()); - // Iteratively access nested fields through the path until we reach the final - // field in the path. - evaluator::EvaluatorValuePtr finalField; - for (auto field : op.getFieldPath().getAsRange()) { - // `currentObject` might no be fully evaluated. - if (!currentObject->getFields().contains(field.getAttr())) - return objectFieldValue; - - auto currentField = currentObject->getField(field.getAttr()); - finalField = currentField.value(); - if (auto *nextObject = - llvm::dyn_cast(finalField.get())) - currentObject = nextObject; - } + auto field = op.getFieldAttr(); + + // `currentObject` might not be fully evaluated. + if (!currentObject->getFields().contains(field)) + return objectFieldValue; + + auto currentField = currentObject->getField(field); + auto finalField = currentField.value(); if (!finalField->isFullyEvaluated()) return objectFieldValue; diff --git a/lib/Dialect/OM/OMOps.cpp b/lib/Dialect/OM/OMOps.cpp index 373b69246a9d..61955376c855 100644 --- a/lib/Dialect/OM/OMOps.cpp +++ b/lib/Dialect/OM/OMOps.cpp @@ -571,6 +571,39 @@ circt::om::ObjectOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return success(); } +//===----------------------------------------------------------------------===// +// ObjectFieldOp +//===----------------------------------------------------------------------===// + +LogicalResult +circt::om::ObjectFieldOp::verifySymbolUses(SymbolTableCollection &symbolTable) { + auto classType = getObject().getType(); + auto className = classType.getClassName().getAttr(); + + // Verify the referred-to class exists. + auto classDef = dyn_cast_or_null( + symbolTable.lookupNearestSymbolFrom(*this, className)); + if (!classDef) + return emitOpError("class ") << className << " was not found"; + + // Verify the field exists in the class. + auto fieldName = getFieldAttr(); + std::optional fieldType = classDef.getFieldType(fieldName); + if (!fieldType) { + auto diag = emitOpError("referenced non-existent field ") << fieldName; + diag.attachNote(classDef.getLoc()) << "class defined here"; + return diag; + } + + // Verify the result type matches the field type. + if (getResult().getType() != fieldType.value()) + return emitOpError("expected type ") + << getResult().getType() << ", but accessed field has type " + << fieldType.value(); + + return success(); +} + //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// diff --git a/lib/Dialect/OM/OMReductions.cpp b/lib/Dialect/OM/OMReductions.cpp index 4a2b539a425a..873400c996ed 100644 --- a/lib/Dialect/OM/OMReductions.cpp +++ b/lib/Dialect/OM/OMReductions.cpp @@ -156,12 +156,8 @@ struct OMClassFieldPruner : public OpReduction { if (!fieldOp) continue; - auto fieldPath = fieldOp.getFieldPath(); - if (fieldPath.empty()) - continue; - // Mark the accessed field as used. - usedFields.insert(cast(fieldPath[0]).getAttr()); + usedFields.insert(fieldOp.getFieldAttr()); } }); diff --git a/lib/Dialect/OM/Transforms/CMakeLists.txt b/lib/Dialect/OM/Transforms/CMakeLists.txt index 13ecd1807833..714b19666539 100644 --- a/lib/Dialect/OM/Transforms/CMakeLists.txt +++ b/lib/Dialect/OM/Transforms/CMakeLists.txt @@ -2,7 +2,6 @@ add_circt_dialect_library(CIRCTOMTransforms FreezePaths.cpp LinkModules.cpp StripOM.cpp - VerifyObjectFields.cpp DEPENDS CIRCTOMTransformsIncGen diff --git a/lib/Dialect/OM/Transforms/FreezePaths.cpp b/lib/Dialect/OM/Transforms/FreezePaths.cpp index af3842770af6..7a1e84c8a273 100644 --- a/lib/Dialect/OM/Transforms/FreezePaths.cpp +++ b/lib/Dialect/OM/Transforms/FreezePaths.cpp @@ -292,7 +292,7 @@ LogicalResult PathVisitor::process(ObjectFieldOp objectFieldOp) { OpBuilder builder(objectFieldOp); auto newObjectFieldOp = ObjectFieldOp::create( builder, objectFieldOp.getLoc(), newResultType, objectFieldOp.getObject(), - objectFieldOp.getFieldPath()); + objectFieldOp.getFieldAttr()); objectFieldOp.replaceAllUsesWith(newObjectFieldOp.getResult()); objectFieldOp->erase(); return success(); diff --git a/lib/Dialect/OM/Transforms/VerifyObjectFields.cpp b/lib/Dialect/OM/Transforms/VerifyObjectFields.cpp deleted file mode 100644 index 23a9df00c505..000000000000 --- a/lib/Dialect/OM/Transforms/VerifyObjectFields.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//===- VerifyObjectFields.cpp - Verify Object fields -------------*- C++-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Contains the definitions of the OM verify object fields pass. -// -//===----------------------------------------------------------------------===// - -#include "circt/Dialect/HW/HWInstanceGraph.h" -#include "circt/Dialect/HW/HWOps.h" -#include "circt/Dialect/HW/InnerSymbolTable.h" -#include "circt/Dialect/OM/OMAttributes.h" -#include "circt/Dialect/OM/OMOps.h" -#include "circt/Dialect/OM/OMPasses.h" -#include "mlir/IR/Threading.h" -#include "mlir/Pass/Pass.h" -#include "llvm/ADT/DenseMap.h" - -namespace circt { -namespace om { -#define GEN_PASS_DEF_VERIFYOBJECTFIELDS -#include "circt/Dialect/OM/OMPasses.h.inc" -} // namespace om -} // namespace circt - -using namespace mlir; -using namespace circt; -using namespace om; - -namespace { -struct VerifyObjectFieldsPass - : public circt::om::impl::VerifyObjectFieldsBase { - using Base::Base; - void runOnOperation() override; - bool canScheduleOn(RegisteredOperationName opName) const override { - return opName.getStringRef() == "firrtl.circuit" || - opName.getStringRef() == "builtin.module"; - } -}; -} // namespace - -void VerifyObjectFieldsPass::runOnOperation() { - auto *module = getOperation(); - assert(module->getNumRegions() == 1 && - module->hasTrait() && - "op must have a single region and symbol table trait"); - auto &symbolTable = getAnalysis(); - - // Run actual verification. Make sure not to mutate `tables`. - auto result = mlir::failableParallelForEach( - &getContext(), module->getRegion(0).getOps(), - [&symbolTable](ClassLike classLike) { - auto result = - classLike.walk([&](ObjectFieldOp objectField) -> WalkResult { - auto objectInstType = - cast(objectField.getObject().getType()); - ClassLike classDef = symbolTable.lookup( - objectInstType.getClassName().getAttr()); - if (!classDef) { - objectField.emitError() - << "class " << objectInstType.getClassName() - << " was not found"; - return WalkResult::interrupt(); - } - - // Traverse the field path, verifying each field exists. - Type finalFieldType; - auto fields = SmallVector( - objectField.getFieldPath().getAsRange()); - for (size_t i = 0, e = fields.size(); i < e; ++i) { - // Verify the field exists on the ClassOp. - auto field = fields[i]; - std::optional fieldTypeOpt = - classDef.getFieldType(field.getAttr()); - - if (!fieldTypeOpt.has_value()) { - auto error = - objectField.emitOpError("referenced non-existent field ") - << field; - error.attachNote(classDef.getLoc()) << "class defined here"; - return WalkResult::interrupt(); - } - Type fieldType = fieldTypeOpt.value(); - - // If there are more fields, verify the current field is of - // ClassType, and look up the ClassOp for that field. - if (i < e - 1) { - auto classType = dyn_cast(fieldType); - if (!classType) { - objectField.emitOpError("nested field access into ") - << field << " requires a ClassType, but found " - << fieldType; - return WalkResult::interrupt(); - } - - // Check if the nested ClassOp exists. ObjectInstOp verifier - // already checked the class exits but it's not verified yet - // if the object is an input argument. - classDef = symbolTable.lookup( - classType.getClassName().getAttr()); - - if (!classDef) { - objectField.emitError() - << "class " << classType.getClassName() - << " was not found"; - return WalkResult::interrupt(); - } - - // Proceed to the next field in the path. - continue; - } - - // On the last iteration down the path, save the final field - // being accessed. - finalFieldType = fieldType; - } - - // Verify the accessed field type matches the result type. - if (finalFieldType != objectField.getResult().getType()) { - objectField.emitOpError("expected type ") - << objectField.getResult().getType() - << ", but accessed field has type " << finalFieldType; - - return WalkResult::interrupt(); - } - return WalkResult::advance(); - }); - return LogicalResult::failure(result.wasInterrupted()); - }); - if (failed(result)) - return signalPassFailure(); - return markAllAnalysesPreserved(); -} diff --git a/lib/Firtool/Firtool.cpp b/lib/Firtool/Firtool.cpp index 21dda32d2cb8..bc7aedec09e9 100644 --- a/lib/Firtool/Firtool.cpp +++ b/lib/Firtool/Firtool.cpp @@ -297,7 +297,6 @@ LogicalResult firtool::populateLowFIRRTLToHW(mlir::PassManager &pm, pm.nest().addPass(firrtl::createLowerDPI()); pm.nest().addPass(firrtl::createLowerDomains()); pm.nest().addPass(firrtl::createLowerClasses()); - pm.nest().addPass(om::createVerifyObjectFields()); // Check for static asserts. pm.nest().addPass(circt::firrtl::createLint( @@ -317,9 +316,6 @@ LogicalResult firtool::populateLowFIRRTLToHW(mlir::PassManager &pm, // Check inner symbols and inner refs. pm.addPass(hw::createVerifyInnerRefNamespace()); - // Check OM object fields. - pm.addPass(om::createVerifyObjectFields()); - // Run the verif op verification pass pm.addNestedPass(verif::createVerifyClockedAssertLikePass()); @@ -369,9 +365,6 @@ LogicalResult firtool::populateHWToSV(mlir::PassManager &pm, // Check inner symbols and inner refs. pm.addPass(hw::createVerifyInnerRefNamespace()); - // Check OM object fields. - pm.addPass(om::createVerifyObjectFields()); - return success(); } @@ -408,9 +401,6 @@ populatePrepareForExportVerilog(mlir::PassManager &pm, // Check inner symbols and inner refs. pm.addPass(hw::createVerifyInnerRefNamespace()); - // Check OM object fields. - pm.addPass(om::createVerifyObjectFields()); - return success(); } } // namespace detail diff --git a/test/Dialect/FIRRTL/lower-classes.mlir b/test/Dialect/FIRRTL/lower-classes.mlir index d8ac439f605b..0a7292bfa97f 100644 --- a/test/Dialect/FIRRTL/lower-classes.mlir +++ b/test/Dialect/FIRRTL/lower-classes.mlir @@ -41,7 +41,7 @@ firrtl.circuit "Component" { %obj0_someReference_in = firrtl.object.subfield %obj0[someReference_in] : !firrtl.class<@Class_0(in someReference_in: !firrtl.class<@Class_1(out someInt: !firrtl.integer)>, out someReference: !firrtl.class<@Class_1(out someInt: !firrtl.integer)>)> firrtl.propassign %obj0_someReference_in, %obj1 : !firrtl.class<@Class_1(out someInt: !firrtl.integer)> - // CHECK: %[[REF:.+]] = om.object.field %[[OBJ0]], [@someReference] : (!om.class.type<@Class_0>) -> !om.class.type<@Class_1> + // CHECK: %[[REF:.+]] = om.object.field %[[OBJ0]]["someReference"] : (!om.class.type<@Class_0>) -> !om.class.type<@Class_1> // CHECK: om.class.fields %[[REF]] : !om.class.type<@Class_1> %obj0_someReference = firrtl.object.subfield %obj0[someReference] : !firrtl.class<@Class_0(in someReference_in: !firrtl.class<@Class_1(out someInt: !firrtl.integer)>, out someReference: !firrtl.class<@Class_1(out someInt: !firrtl.integer)>)> firrtl.propassign %obj_0_out, %obj0_someReference: !firrtl.class<@Class_1(out someInt: !firrtl.integer)> @@ -51,7 +51,7 @@ firrtl.circuit "Component" { // CHECK-SAME: -> (output: !om.integer) firrtl.class @ReadOutputPort(out %output : !firrtl.integer) { // CHECK: %[[OBJ:.+]] = om.object @Class_1(%basepath) : (!om.basepath) -> !om.class.type<@Class_1> - // CHECK: %[[FIELD:.+]] = om.object.field %[[OBJ]], [@someInt] : (!om.class.type<@Class_1>) -> !om.integer + // CHECK: %[[FIELD:.+]] = om.object.field %[[OBJ]]["someInt"] : (!om.class.type<@Class_1>) -> !om.integer // CHECK: om.class.fields %[[FIELD]] : !om.integer %obj = firrtl.object @Class_1(out someInt: !firrtl.integer) %0 = firrtl.object.subfield %obj[someInt] : !firrtl.class<@Class_1(out someInt: !firrtl.integer)> @@ -336,12 +336,12 @@ firrtl.circuit "ModuleInstances" { // CHECK: om.class @ModuleInstances_Class(%basepath: !om.basepath, %[[IN_PROP1:.+]]: !om.string) -> (outputProp: !om.string) // CHECK: %[[BASEPATH:.+]] = om.basepath_create %basepath @[[EXT_NLA]] // CHECK: %[[O0:.+]] = om.object @ExtModule_Class(%[[BASEPATH]], %[[IN_PROP1]]) - // CHECK: %[[F0:.+]] = om.object.field %[[O0]], [@outputProp] + // CHECK: %[[F0:.+]] = om.object.field %[[O0]]["outputProp"] // CHECK: %[[BASEPATH:.+]] = om.basepath_create %basepath @[[EXTDEFNAME_NLA]] // CHECK: om.object @TheRealName_Class // CHECK: %[[BASEPATH:.+]] = om.basepath_create %basepath @[[MOD_NLA]] // CHECK: %[[O1:.+]] = om.object @Module_Class(%[[BASEPATH]], %[[F0]]) - // CHECK: %[[F1:.+]] = om.object.field %[[O1]], [@outputProp] + // CHECK: %[[F1:.+]] = om.object.field %[[O1]]["outputProp"] // CHECK: om.class.fields %[[F1]] : !om.string } @@ -549,6 +549,8 @@ firrtl.circuit "PathTargetReplaced" { %path = firrtl.path instance distinct[0]<> } firrtl.module private @WillBeReplaced(out %output: !firrtl.integer) { + %c = firrtl.integer 42 + firrtl.propassign %output, %c : !firrtl.integer } } diff --git a/test/Dialect/OM/Reduction/class-field-pruner.mlir b/test/Dialect/OM/Reduction/class-field-pruner.mlir index a29606a1c8a5..b71c88f8999e 100644 --- a/test/Dialect/OM/Reduction/class-field-pruner.mlir +++ b/test/Dialect/OM/Reduction/class-field-pruner.mlir @@ -21,8 +21,8 @@ module { %1 = om.object @Foo(%0) : (!om.integer) -> !om.class.type<@Foo> // Only access the usedField - the other fields should be removed - // CHECK: om.object.field %{{.+}}, [@usedField] - %2 = om.object.field %1, [@usedField] : (!om.class.type<@Foo>) -> !om.integer + // CHECK: om.object.field %{{.+}}["usedField"] + %2 = om.object.field %1["usedField"] : (!om.class.type<@Foo>) -> !om.integer om.class.fields } diff --git a/test/Dialect/OM/errors.mlir b/test/Dialect/OM/errors.mlir index 9d72257c5cf8..3fee2e14ad7b 100644 --- a/test/Dialect/OM/errors.mlir +++ b/test/Dialect/OM/errors.mlir @@ -1,4 +1,4 @@ -// RUN: circt-opt -om-verify-object-fields %s -verify-diagnostics -split-input-file +// RUN: circt-opt %s -verify-diagnostics -split-input-file om.class @Class() { // expected-error @+1 {{'om.object' op result type ("Bar") does not match referred to class ("Foo")}} @@ -49,22 +49,8 @@ om.class @Class1() { om.class @Class2() { %0 = om.object @Class1() : () -> !om.class.type<@Class1> - // expected-error @+1 {{'om.object.field' op referenced non-existent field @foo}} - om.object.field %0, [@foo] : (!om.class.type<@Class1>) -> i1 - om.class.fields -} - -// ----- - -om.class @Class1() -> (foo: i1) { - %0 = om.constant 1 : i1 - om.class.fields %0 : i1 -} - -om.class @Class2() { - %0 = om.object @Class1() : () -> !om.class.type<@Class1> - // expected-error @+1 {{'om.object.field' op nested field access into @foo requires a ClassType, but found 'i1'}} - om.object.field %0, [@foo, @bar] : (!om.class.type<@Class1>) -> i1 + // expected-error @+1 {{'om.object.field' op referenced non-existent field "foo"}} + om.object.field %0["foo"] : (!om.class.type<@Class1>) -> i1 om.class.fields } @@ -78,7 +64,7 @@ om.class @Class1() -> (foo: i1) { om.class @Class2(%arg0: i1) { %0 = om.object @Class1() : () -> !om.class.type<@Class1> // expected-error @+1 {{'om.object.field' op expected type 'i2', but accessed field has type 'i1'}} - om.object.field %0, [@foo] : (!om.class.type<@Class1>) -> i2 + om.object.field %0["foo"] : (!om.class.type<@Class1>) -> i2 om.class.fields } @@ -134,8 +120,8 @@ om.class @DupField(%0: i1) -> (foo: i1, foo: i1){ // ----- om.class @UnknownClass(%arg: !om.class.type<@Unknwon>) { - // expected-error @+1 {{class @Unknwon was not found}} - om.object.field %arg, [@unknown]: (!om.class.type<@Unknwon>) -> i1 + // expected-error @+1 {{class "Unknwon" was not found}} + om.object.field %arg["unknown"]: (!om.class.type<@Unknwon>) -> i1 om.class.fields } diff --git a/test/Dialect/OM/freeze-paths.mlir b/test/Dialect/OM/freeze-paths.mlir index 4370c9ffd989..1a5b0e86b57e 100644 --- a/test/Dialect/OM/freeze-paths.mlir +++ b/test/Dialect/OM/freeze-paths.mlir @@ -113,12 +113,12 @@ om.class @PathListTest(%arg : !om.list) { } // CHECK-LABEL: om.class @ObjectFieldTest -om.class @ObjectFieldTest(%basepath : !om.basepath, %path : !om.path) -> (subfield: !om.list>) { - // CHECK: [[OBJ:%.+]] = om.object @PathTest - %0 = om.object @PathTest(%basepath, %path) : (!om.basepath, !om.path) -> !om.class.type<@PathTest> +om.class @ObjectFieldTest(%notpath: i1, %basepath : !om.basepath, %path : !om.path) -> (subfield: !om.list>) { + // CHECK: [[OBJ:%.+]] = om.object @ListCreateTest + %0 = om.object @ListCreateTest(%notpath, %basepath, %path) : (i1, !om.basepath, !om.path) -> !om.class.type<@ListCreateTest> - // CHECK: [[SUBFIELD:%.+]] = om.object.field [[OBJ]], [@nestedpath] : (!om.class.type<@PathTest>) -> !om.list> - %1 = om.object.field %0, [@nestedpath] : (!om.class.type<@PathTest>) -> !om.list> + // CHECK: [[SUBFIELD:%.+]] = om.object.field [[OBJ]]["nestedpath"] : (!om.class.type<@ListCreateTest>) -> !om.list> + %1 = om.object.field %0["nestedpath"] : (!om.class.type<@ListCreateTest>) -> !om.list> // CHECK: om.class.fields [[SUBFIELD]] : !om.list> om.class.fields %1 : !om.list> diff --git a/test/Dialect/OM/link-modules.mlir b/test/Dialect/OM/link-modules.mlir index d4409d18efe3..f1c934840943 100644 --- a/test/Dialect/OM/link-modules.mlir +++ b/test/Dialect/OM/link-modules.mlir @@ -14,12 +14,12 @@ module { // CHECK-LABEL: om.class @Conflict_B // CHECK-LABEL: om.class @UseConflict_B() // CHECK-NEXT: om.object @Conflict_B() : () -> !om.class.type<@Conflict_B> - // CHECK-NEXT: om.object.field %{{.+}}, [@c] : (!om.class.type<@Conflict_B>) -> i1 + // CHECK-NEXT: om.object.field %{{.+}}["c"] : (!om.class.type<@Conflict_B>) -> i1 // CHECK-LABEL: om.class @Conflict_module_0() // CHECK-LABEL: om.class @UseConflict_module_0() // CHECK-NEXT: om.object @Conflict_module_0() : () -> !om.class.type<@Conflict_module_0> - // CHECK-NEXT: om.object.field %{{.+}}, [@c] : (!om.class.type<@Conflict_module_0>) -> i1 + // CHECK-NEXT: om.object.field %{{.+}}["c"] : (!om.class.type<@Conflict_module_0>) -> i1 module attributes {om.namespace = "A"} { om.class @A(%arg: i1) -> (a: i1) { @@ -42,7 +42,7 @@ module { } om.class @UseConflict() -> (c: i1) { %0 = om.object @Conflict() : () -> !om.class.type<@Conflict> - %1 = om.object.field %0, [@c] : (!om.class.type<@Conflict>) -> i1 + %1 = om.object.field %0["c"] : (!om.class.type<@Conflict>) -> i1 om.class.fields %1 : i1 } } @@ -53,7 +53,7 @@ module { } om.class @UseConflict() { %0 = om.object @Conflict() : () -> !om.class.type<@Conflict> - %1 = om.object.field %0, [@c] : (!om.class.type<@Conflict>) -> i1 + %1 = om.object.field %0["c"] : (!om.class.type<@Conflict>) -> i1 om.class.fields } } diff --git a/test/Dialect/OM/round-trip.mlir b/test/Dialect/OM/round-trip.mlir index d862a75d04e4..701481f0e605 100644 --- a/test/Dialect/OM/round-trip.mlir +++ b/test/Dialect/OM/round-trip.mlir @@ -17,8 +17,8 @@ om.class @Thingy(%blue_1: i8, %blue_2: i32) -> (widget: !om.class.type<@Widget>, // CHECK: %[[gadget:.+]] = om.object @Gadget(%[[c7]], %[[c8]]) : (i8, i32) -> !om.class.type<@Gadget> %5 = om.object @Gadget(%3, %4) : (i8, i32) -> !om.class.type<@Gadget> - // CHECK: %[[widget_field:.+]] = om.object.field %[[widget]], [@blue_1] : (!om.class.type<@Widget>) -> i8 - %6 = om.object.field %2, [@blue_1] : (!om.class.type<@Widget>) -> i8 + // CHECK: %[[widget_field:.+]] = om.object.field %[[widget]]["blue_1"] : (!om.class.type<@Widget>) -> i8 + %6 = om.object.field %2["blue_1"] : (!om.class.type<@Widget>) -> i8 // CHECK: om.class.fields {test = "fieldsAttr"} %2, %5, %blue_1, %6 : !om.class.type<@Widget>, !om.class.type<@Gadget>, i8, i8 field_locs([loc("loc0"), loc("loc1"), loc("loc2"), loc("loc3")]) loc("test") om.class.fields {test = "fieldsAttr"} %2, %5, %blue_1, %6 : !om.class.type<@Widget>, !om.class.type<@Gadget>, i8, i8 field_locs([loc("loc0"), loc("loc1"), loc("loc2"), loc("loc3")]) loc("test") @@ -59,8 +59,8 @@ om.class @ExternObject(%param1: i1, %param2: i2) { // CHECK: %[[O0:.+]] = om.object @Extern(%[[P0]], %[[P1]]) %0 = om.object @Extern(%param1, %param2) : (i1, i2) -> !om.class.type<@Extern> - // CHECK: om.object.field %[[O0]], [@field1] - %1 = om.object.field %0, [@field1] : (!om.class.type<@Extern>) -> i3 + // CHECK: om.object.field %[[O0]]["field1"] + %1 = om.object.field %0["field1"] : (!om.class.type<@Extern>) -> i3 om.class.fields } @@ -83,8 +83,8 @@ om.class @NestedField3() -> (foo: !om.class.type<@NestedField2>) { om.class @NestedField4() { // CHECK: %[[nested:.+]] = om.object @NestedField3 %0 = om.object @NestedField3() : () -> !om.class.type<@NestedField3> - // CHECK: %{{.+}} = om.object.field %[[nested]], [@foo, @bar, @baz] : (!om.class.type<@NestedField3>) -> i1 - %1 = om.object.field %0, [@foo, @bar, @baz] : (!om.class.type<@NestedField3>) -> i1 + // CHECK: %{{.+}} = om.object.field %[[nested]]["foo"] : (!om.class.type<@NestedField3>) -> !om.class.type<@NestedField2> + %1 = om.object.field %0["foo"] : (!om.class.type<@NestedField3>) -> !om.class.type<@NestedField2> om.class.fields } @@ -238,13 +238,13 @@ om.class @ReferenceEachOther() { om.class @RefecenceEachOthersField(%blue_1: i8, %green_1: i32) { // CHECK-NEXT: %[[obj1:.+]] = om.object @Widget(%blue_1, %[[field2:.+]]) : (i8, i32) -> !om.class.type<@Widget> %0 = om.object @Widget(%blue_1, %3) : (i8, i32) -> !om.class.type<@Widget> - // CHECK-NEXT: %[[field1:.+]] = om.object.field %[[obj1]], [@blue_1] : (!om.class.type<@Widget>) -> i8 - %1 = om.object.field %0, [@blue_1] : (!om.class.type<@Widget>) -> i8 + // CHECK-NEXT: %[[field1:.+]] = om.object.field %[[obj1]]["blue_1"] : (!om.class.type<@Widget>) -> i8 + %1 = om.object.field %0["blue_1"] : (!om.class.type<@Widget>) -> i8 // CHECK-NEXT: %[[obj2:.+]] = om.object @Widget(%[[field1]], %green_1) : (i8, i32) -> !om.class.type<@Widget> %2 = om.object @Widget(%1, %green_1) : (i8, i32) -> !om.class.type<@Widget> - // CHECK-NEXT: %[[field2]] = om.object.field %[[obj2]], [@green_1] : (!om.class.type<@Widget>) -> i32 - %3 = om.object.field %2, [@green_1] : (!om.class.type<@Widget>) -> i32 + // CHECK-NEXT: %[[field2]] = om.object.field %[[obj2]]["green_1"] : (!om.class.type<@Widget>) -> i32 + %3 = om.object.field %2["green_1"] : (!om.class.type<@Widget>) -> i32 om.class.fields } diff --git a/unittests/Dialect/OM/Evaluator/EvaluatorTests.cpp b/unittests/Dialect/OM/Evaluator/EvaluatorTests.cpp index e9a02a5df2c8..78e89bcd8570 100644 --- a/unittests/Dialect/OM/Evaluator/EvaluatorTests.cpp +++ b/unittests/Dialect/OM/Evaluator/EvaluatorTests.cpp @@ -367,11 +367,9 @@ TEST(EvaluatorTests, InstantiateObjectWithFieldAccess) { body.addArgument(circt::om::OMIntegerType::get(&context), cls.getLoc()); builder.setInsertionPointToStart(&body); auto object = ObjectOp::create(builder, innerCls, body.getArguments()); - auto field = - ObjectFieldOp::create(builder, builder.getI32Type(), object, - builder.getArrayAttr(FlatSymbolRefAttr::get( - builder.getStringAttr("field")))); - ClassFieldsOp::create(builder, loc, SmallVector({field}), ArrayAttr{}); + auto field = ObjectFieldOp::create(builder, builder.getI32Type(), object, + builder.getStringAttr("field")); + ClassFieldsOp::create(builder, loc, ValueRange{field}, ArrayAttr{}); Evaluator evaluator(mod); @@ -586,7 +584,9 @@ om.class @LinkedList(%n: !ty, %val: !om.string) -> (n: !ty, val: } om.class @ReferenceEachOther() -> (field1: !ty, field2: !ty) { %str = om.constant "foo" : !om.string - %val = om.object.field %1, [@n, @n, @val] : (!ty) -> !om.string + %temp1 = om.object.field %1["n"] : (!ty) -> !ty + %temp2 = om.object.field %temp1["n"] : (!ty) -> !ty + %val = om.object.field %temp2["val"] : (!ty) -> !om.string %0 = om.object @LinkedList(%1, %val) : (!ty, !om.string) -> !ty %1 = om.object @LinkedList(%0, %str) : (!ty, !om.string) -> !ty om.class.fields %0, %1 : !ty, !ty @@ -641,7 +641,7 @@ om.class @LinkedList(%n: !ty) -> (n: !ty){ om.class.fields %n : !ty } om.class @ReferenceEachOther() -> (field: !ty){ - %val = om.object.field %0, [@n] : (!ty) -> !ty + %val = om.object.field %0["n"] : (!ty) -> !ty %0 = om.object @LinkedList(%val) : (!ty) -> !ty om.class.fields %0 : !ty } @@ -681,9 +681,9 @@ om.class @Domain(%in: !om.string) -> (out: !om.string) { om.class @Top() -> (test: i1) { %0 = om.constant "A" : !om.string %1 = om.object @Domain(%0) : (!om.string) -> !om.class.type<@Domain> - %2 = om.object.field %1, [@out] : (!om.class.type<@Domain>) -> !om.string + %2 = om.object.field %1["out"] : (!om.class.type<@Domain>) -> !om.string %3 = om.object @Domain(%2) : (!om.string) -> !om.class.type<@Domain> - %4 = om.object.field %3, [@out] : (!om.class.type<@Domain>) -> !om.string + %4 = om.object.field %3["out"] : (!om.class.type<@Domain>) -> !om.string %5 = om.constant "B" : !om.string %6 = om.prop.eq %4, %5 : !om.string om.class.fields %6 : i1 @@ -1014,10 +1014,10 @@ om.class @Class2() -> (value: !om.integer){ om.class @IntegerBinaryArithmeticObjects() -> (result: !om.integer) { %0 = om.object @Class1() : () -> !om.class.type<@Class1> - %1 = om.object.field %0, [@value] : (!om.class.type<@Class1>) -> !om.integer + %1 = om.object.field %0["value"] : (!om.class.type<@Class1>) -> !om.integer %2 = om.object @Class2() : () -> !om.class.type<@Class2> - %3 = om.object.field %2, [@value] : (!om.class.type<@Class2>) -> !om.integer + %3 = om.object.field %2["value"] : (!om.class.type<@Class2>) -> !om.integer %5 = om.integer.add %1, %3 : !om.integer om.class.fields %5 : !om.integer @@ -1064,10 +1064,10 @@ om.class @Class2() -> (value: !om.integer){ om.class @IntegerBinaryArithmeticObjectsDelayed() -> (result: !om.integer){ %0 = om.object @Class1(%5) : (!om.integer) -> !om.class.type<@Class1> - %1 = om.object.field %0, [@value] : (!om.class.type<@Class1>) -> !om.integer + %1 = om.object.field %0["value"] : (!om.class.type<@Class1>) -> !om.integer %2 = om.object @Class2() : () -> !om.class.type<@Class2> - %3 = om.object.field %2, [@value] : (!om.class.type<@Class2>) -> !om.integer + %3 = om.object.field %2["value"] : (!om.class.type<@Class2>) -> !om.integer %5 = om.integer.add %1, %3 : !om.integer om.class.fields %5 : !om.integer @@ -1202,7 +1202,7 @@ om.class @ListConcatField() -> (result: !om.list){ %0 = om.constant #om.integer<0 : i8> : !om.integer %1 = om.constant #om.integer<1 : i8> : !om.integer %l0 = om.list_create %0, %1 : !om.integer - %l1 = om.object.field %listField, [@value] : (!om.class.type<@ListField>) -> !om.list + %l1 = om.object.field %listField["value"] : (!om.class.type<@ListField>) -> !om.list %concat = om.list_concat %l0, %l1 : !om.list om.class.fields %concat : !om.list } @@ -1328,9 +1328,9 @@ om.class @Leaf(%id_in: !om.integer) -> (id: !om.integer) { } om.class @ListConcatPartialCycle() -> (result: !om.list){ %0 = om.object @Child(%7) : (!om.any) -> !om.class.type<@Child> - %1 = om.object.field %0, [@field] : (!om.class.type<@Child>) -> !om.list + %1 = om.object.field %0["field"] : (!om.class.type<@Child>) -> !om.list %2 = om.object @Child(%10) : (!om.any) -> !om.class.type<@Child> - %3 = om.object.field %2, [@field] : (!om.class.type<@Child>) -> !om.list + %3 = om.object.field %2["field"] : (!om.class.type<@Child>) -> !om.list %4 = om.list_concat %1, %3 : %5 = om.constant #om.integer<1 : i64> %6 = om.object @Leaf(%5) : (!om.integer) -> !om.class.type<@Leaf> @@ -1399,9 +1399,9 @@ om.class @InnerClass2(%anyListIn: !om.list) -> (any_list2: !om.list (om: !om.class.type<@InnerClass2>) { %0 = om.object @InnerClass2(%5) : (!om.list) -> !om.class.type<@InnerClass2> %1 = om.object @Any() : () -> !om.class.type<@Any> - %2 = om.object.field %1, [@object] : (!om.class.type<@Any>) -> !om.any + %2 = om.object.field %1["object"] : (!om.class.type<@Any>) -> !om.any %3 = om.object @Any() : () -> !om.class.type<@Any> - %4 = om.object.field %3, [@object] : (!om.class.type<@Any>) -> !om.any + %4 = om.object.field %3["object"] : (!om.class.type<@Any>) -> !om.any %5 = om.list_create %2, %4 : !om.any om.class.fields %0 : !om.class.type<@InnerClass2> } @@ -1409,10 +1409,10 @@ om.class @OuterClass1() -> (om: !om.any) { %0 = om.object @InnerClass1(%8) : (!om.list) -> !om.class.type<@InnerClass1> %1 = om.any_cast %0 : (!om.class.type<@InnerClass1>) -> !om.any %2 = om.object @OuterClass2() : () -> !om.class.type<@OuterClass2> - %3 = om.object.field %2, [@om] : (!om.class.type<@OuterClass2>) -> !om.class.type<@InnerClass2> + %3 = om.object.field %2["om"] : (!om.class.type<@OuterClass2>) -> !om.class.type<@InnerClass2> %4 = om.any_cast %3 : (!om.class.type<@InnerClass2>) -> !om.any %5 = om.object @OuterClass2() : () -> !om.class.type<@OuterClass2> - %6 = om.object.field %5, [@om] : (!om.class.type<@OuterClass2>) -> !om.class.type<@InnerClass2> + %6 = om.object.field %5["om"] : (!om.class.type<@OuterClass2>) -> !om.class.type<@InnerClass2> %7 = om.any_cast %6 : (!om.class.type<@InnerClass2>) -> !om.any %8 = om.list_create %4, %7 : !om.any om.class.fields %1 : !om.any @@ -1539,10 +1539,10 @@ om.class @Foo( %3 = om.list_concat %2, %2 : !om.list %4 = om.frozenbasepath_create %unknown_frozenbasepath "Foo/bar" %5 = om.frozenpath_create reference %unknown_frozenbasepath "Foo/bar:Bar>w.a" - %6 = om.object.field %unknown_class, [@b] : (!om.class.type<@Bar>) -> !om.integer + %6 = om.object.field %unknown_class["b"] : (!om.class.type<@Bar>) -> !om.integer %7 = om.unknown : !om.integer %8 = om.object @Baz() : () -> !om.class.type<@Baz> - %9 = om.object.field %8, [@a] : (!om.class.type<@Baz>) -> !om.integer + %9 = om.object.field %8["a"] : (!om.class.type<@Baz>) -> !om.integer %10 = om.unknown : !om.integer %11 = om.unknown : !om.string %12 = om.unknown : !om.list @@ -1661,8 +1661,8 @@ om.class @Foo( %0 = om.constant #om.integer<1 : i4> : !om.integer %bar = om.object @Bar(%0, %unknown_in) : (!om.integer, !om.integer) -> !om.class.type<@Bar> - %1 = om.object.field %bar, [@known_out] : (!om.class.type<@Bar>) -> !om.integer - %2 = om.object.field %bar, [@unknown_out] : (!om.class.type<@Bar>) -> !om.integer + %1 = om.object.field %bar["known_out"] : (!om.class.type<@Bar>) -> !om.integer + %2 = om.object.field %bar["unknown_out"] : (!om.class.type<@Bar>) -> !om.integer om.class.fields %0, %2 : !om.integer, !om.integer } @@ -1755,7 +1755,7 @@ om.class.extern @Dut_Class(%basepath: !om.frozenbasepath) -> (omirOut: !om.list< om.class @TestHarness_Class(%basepath: !om.frozenbasepath) -> (result: !om.list) { %0 = om.frozenbasepath_create %basepath "TestHarness/dut" %1 = om.object @Dut_Class(%0) : (!om.frozenbasepath) -> !om.class.type<@Dut_Class> - %2 = om.object.field %1, [@omirOut] : (!om.class.type<@Dut_Class>) -> !om.list + %2 = om.object.field %1["omirOut"] : (!om.class.type<@Dut_Class>) -> !om.list %3 = om.list_create : !om.any %4 = om.list_concat %3, %2 : !om.list om.class.fields %4 : !om.list @@ -1842,7 +1842,7 @@ om.class @Parameter_True_Cycle(%in: i1) -> (out: i1) { } om.class @Parameter_True_Cycle_Top() -> () { %obj = om.object @Parameter_True_Cycle(%in) : (i1) -> !om.class.type<@Parameter_True_Cycle> - %in = om.object.field %obj, [@out] : (!om.class.type<@Parameter_True_Cycle>) -> i1 + %in = om.object.field %obj["out"] : (!om.class.type<@Parameter_True_Cycle>) -> i1 om.class.fields } @@ -1854,7 +1854,7 @@ om.class @Parameter_False_Cycle(%in: i1) -> (out: i1) { } om.class @Parameter_False_Cycle_Top() -> () { %obj = om.object @Parameter_False_Cycle(%in) : (i1) -> !om.class.type<@Parameter_False_Cycle> - %in = om.object.field %obj, [@out] : (!om.class.type<@Parameter_False_Cycle>) -> i1 + %in = om.object.field %obj["out"] : (!om.class.type<@Parameter_False_Cycle>) -> i1 om.class.fields } @@ -1865,7 +1865,7 @@ om.class @ReturnTrue() -> (out: i1) { } om.class @SubfieldTrue() -> () { %obj = om.object @ReturnTrue() : () -> !om.class.type<@ReturnTrue> - %true = om.object.field %obj, [@out] : (!om.class.type<@ReturnTrue>) -> i1 + %true = om.object.field %obj["out"] : (!om.class.type<@ReturnTrue>) -> i1 om.property_assert %true, "input must be true true" : i1 om.class.fields } @@ -1877,7 +1877,7 @@ om.class @ReturnFalse() -> (out: i1) { } om.class @SubfieldFalse() -> () { %obj = om.object @ReturnFalse() : () -> !om.class.type<@ReturnFalse> - %false = om.object.field %obj, [@out] : (!om.class.type<@ReturnFalse>) -> i1 + %false = om.object.field %obj["out"] : (!om.class.type<@ReturnFalse>) -> i1 om.property_assert %false, "input must be true true" : i1 om.class.fields } @@ -1892,9 +1892,9 @@ om.class @Domain(%in: !om.string) -> (out: !om.string) { om.class @ChainedDomainAssert(%basepath: !om.frozenbasepath) -> () { %0 = om.constant "A" : !om.string %1 = om.object @Domain(%0) : (!om.string) -> !om.class.type<@Domain> - %2 = om.object.field %1, [@out] : (!om.class.type<@Domain>) -> !om.string + %2 = om.object.field %1["out"] : (!om.class.type<@Domain>) -> !om.string %3 = om.object @Domain(%2) : (!om.string) -> !om.class.type<@Domain> - %4 = om.object.field %3, [@out] : (!om.class.type<@Domain>) -> !om.string + %4 = om.object.field %3["out"] : (!om.class.type<@Domain>) -> !om.string %5 = om.constant "B" : !om.string %6 = om.prop.eq %4, %5 : !om.string om.property_assert %6, "hello" : i1 From e6dc38a50acfd9d689b14b44f9466191f43eaddb Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Mon, 27 Apr 2026 18:23:51 -0700 Subject: [PATCH 2/3] Update field access syntax for Widget object --- test/Dialect/OM/round-trip.mlir | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Dialect/OM/round-trip.mlir b/test/Dialect/OM/round-trip.mlir index 277082d5a008..d61afdaf2711 100644 --- a/test/Dialect/OM/round-trip.mlir +++ b/test/Dialect/OM/round-trip.mlir @@ -50,8 +50,8 @@ om.class @ElaboratedWidget() -> (widget: !om.class.type<@Widget>, blue: i8) { %1 = om.constant 6 : i32 // CHECK: %[[widget:.+]] = om.elaborated_object @Widget(%{{.+}}, %{{.+}}) : (i8, i32) -> !om.class.type<@Widget> %2 = om.elaborated_object @Widget(%0, %1) : (i8, i32) -> !om.class.type<@Widget> - // CHECK: %[[blue:.+]] = om.object.field %[[widget]], [@blue_1] : (!om.class.type<@Widget>) -> i8 - %3 = om.object.field %2, [@blue_1] : (!om.class.type<@Widget>) -> i8 + // CHECK: %[[blue:.+]] = om.object.field %[[widget]]["blue_1"] : (!om.class.type<@Widget>) -> i8 + %3 = om.object.field %2["blue_1"] : (!om.class.type<@Widget>) -> i8 // CHECK: om.class.fields %[[widget]], %[[blue]] : !om.class.type<@Widget>, i8 om.class.fields %2, %3 : !om.class.type<@Widget>, i8 } From d821f9218932bfb131313b3fd08d41db828d677f Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Tue, 28 Apr 2026 13:47:34 -0700 Subject: [PATCH 3/3] Remove unnecessary blank line in OMOps.td --- include/circt/Dialect/OM/OMOps.td | 1 - 1 file changed, 1 deletion(-) diff --git a/include/circt/Dialect/OM/OMOps.td b/include/circt/Dialect/OM/OMOps.td index ca0f7e2934f8..d01f2bd2b8e0 100644 --- a/include/circt/Dialect/OM/OMOps.td +++ b/include/circt/Dialect/OM/OMOps.td @@ -206,7 +206,6 @@ def ObjectOp : OMOp<"object", [ }]; } - def ElaboratedObjectOp : OMOp<"elaborated_object", [ DeclareOpInterfaceMethods, ]> {