19#include "mlir/IR/Threading.h"
20#include "mlir/Pass/Pass.h"
21#include "llvm/ADT/DenseMap.h"
25#define GEN_PASS_DEF_VERIFYOBJECTFIELDS
26#include "circt/Dialect/OM/OMPasses.h.inc"
35struct VerifyObjectFieldsPass
36 :
public circt::om::impl::VerifyObjectFieldsBase<VerifyObjectFieldsPass> {
37 void runOnOperation()
override;
38 bool canScheduleOn(RegisteredOperationName opName)
const override {
39 return opName.getStringRef() ==
"firrtl.circuit" ||
40 opName.getStringRef() ==
"builtin.module";
45void VerifyObjectFieldsPass::runOnOperation() {
46 auto *
module = getOperation();
47 assert(module->getNumRegions() == 1 &&
48 module->hasTrait<OpTrait::SymbolTable>() &&
49 "op must have a single region and symbol table trait");
50 auto &symbolTable = getAnalysis<SymbolTable>();
53 auto result = mlir::failableParallelForEach(
54 &getContext(), module->getRegion(0).getOps<om::ClassLike>(),
55 [&symbolTable](ClassLike classLike) {
57 classLike.walk([&](ObjectFieldOp objectField) -> WalkResult {
59 cast<ClassType>(objectField.getObject().getType());
60 ClassLike classDef = symbolTable.lookup<ClassLike>(
61 objectInstType.getClassName().getAttr());
63 objectField.emitError()
64 <<
"class " << objectInstType.getClassName()
66 return WalkResult::interrupt();
71 auto fields = SmallVector<FlatSymbolRefAttr>(
72 objectField.getFieldPath().getAsRange<FlatSymbolRefAttr>());
73 for (size_t i = 0, e = fields.size(); i < e; ++i) {
75 auto field = fields[i];
76 std::optional<Type> fieldTypeOpt =
77 classDef.getFieldType(field.getAttr());
79 if (!fieldTypeOpt.has_value()) {
81 objectField.emitOpError(
"referenced non-existent field ")
83 error.attachNote(classDef.getLoc()) <<
"class defined here";
84 return WalkResult::interrupt();
86 Type fieldType = fieldTypeOpt.value();
91 auto classType = dyn_cast<ClassType>(fieldType);
93 objectField.emitOpError(
"nested field access into ")
94 << field <<
" requires a ClassType, but found "
96 return WalkResult::interrupt();
102 classDef = symbolTable.lookup<ClassOp>(
103 classType.getClassName().getAttr());
106 objectField.emitError()
107 <<
"class " << classType.getClassName()
109 return WalkResult::interrupt();
118 finalFieldType = fieldType;
122 if (finalFieldType != objectField.getResult().getType()) {
123 objectField.emitOpError(
"expected type ")
124 << objectField.getResult().getType()
125 <<
", but accessed field has type " << finalFieldType;
127 return WalkResult::interrupt();
129 return WalkResult::advance();
131 return LogicalResult::failure(result.wasInterrupted());
134 return signalPassFailure();
135 return markAllAnalysesPreserved();
139 return std::make_unique<VerifyObjectFieldsPass>();
assert(baseType &&"element must be base type")
std::unique_ptr< mlir::Pass > createVerifyObjectFieldsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.