mirror of https://github.com/llvm/circt.git
[OM] Add ClassOp region verifier
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 <schuyler.eldridge@sifive.com>
This commit is contained in:
parent
b76a3629d2
commit
e08011253e
|
@ -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,
|
||||
|
|
|
@ -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 ®ion, OpAsmSetValueNameFn setNameFn) {
|
||||
getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue