Skip to content

Commit

Permalink
[OM] Add ClassOp region verifier
Browse files Browse the repository at this point in the history
Add a region verifier to OM dialect's Class Op.  This verifies that the
terminator returns the right number of fields with the correct types that
match the declared type of the Class Op.

Fixes #7736.

Signed-off-by: Schuyler Eldridge <[email protected]>
  • Loading branch information
seldridge committed Oct 28, 2024
1 parent b76a362 commit e080112
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/circt/Dialect/OM/OMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ def ClassOp : OMClassLike<"class", [
// assertion error
mlir::Location getFieldLocByIndex(size_t i);
}];

let hasRegionVerifier = 1;
}

def ClassFieldsOp : OMOp<"class.fields", [Terminator, ReturnLike, Pure,
Expand Down
29 changes: 29 additions & 0 deletions lib/Dialect/OM/OMOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,35 @@ void circt::om::ClassOp::print(OpAsmPrinter &printer) {

LogicalResult circt::om::ClassOp::verify() { return verifyClassLike(*this); }

LogicalResult circt::om::ClassOp::verifyRegions() {
auto fieldsOp = cast<ClassFieldsOp>(this->getBodyBlock()->getTerminator());

// The number of results matches the number of terminator operands.
if (fieldsOp.getNumOperands() != this->getFieldNames().size()) {
auto diag = this->emitOpError()
<< "returns '" << this->getFieldNames().size()
<< "' fields, but its terminator returned '"
<< fieldsOp.getNumOperands() << "' fields";
return diag.attachNote(fieldsOp.getLoc()) << "see terminator:";
}

// The type of each result matches the corresponding terminator operand type.
auto types = this->getFieldTypes();
for (auto [fieldName, terminatorOperandType] :
llvm::zip(this->getFieldNames(), fieldsOp.getOperandTypes())) {

if (terminatorOperandType ==
cast<TypeAttr>(types.get(cast<StringAttr>(fieldName))).getValue())
continue;

auto diag = this->emitOpError()
<< "returns different field types than its terminator";
return diag.attachNote(fieldsOp.getLoc()) << "see terminator:";
}

return success();
}

void circt::om::ClassOp::getAsmBlockArgumentNames(
Region &region, OpAsmSetValueNameFn setNameFn) {
getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
Expand Down
17 changes: 17 additions & 0 deletions test/Dialect/OM/errors.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,20 @@ om.class @UnknownClass(%arg: !om.class.type<@Unknwon>) {
om.object.field %arg, [@unknown]: (!om.class.type<@Unknwon>) -> i1
om.class.fields
}

// -----

// expected-error @+1 {{returns '0' fields, but its terminator returned '1' fields}}
om.class @A(%arg: i1) {
// expected-note @+1 {{see terminator:}}
om.class.fields %arg : i1
}


// -----

// expected-error @+1 {{returns different field types than its terminator}}
om.class @A(%arg: i1) -> (a: i2) {
// expected-note @+1 {{see terminator:}}
om.class.fields %arg : i1
}

0 comments on commit e080112

Please sign in to comment.