Loading [MathJax]/extensions/tex2jax.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
VerifyObjectFields.cpp
Go to the documentation of this file.
1//===- VerifyObjectFields.cpp - Verify Object fields -------------*- C++-*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Contains the definitions of the OM verify object fields pass.
10//
11//===----------------------------------------------------------------------===//
12
19#include "mlir/IR/Threading.h"
20#include "mlir/Pass/Pass.h"
21#include "llvm/ADT/DenseMap.h"
22
23namespace circt {
24namespace om {
25#define GEN_PASS_DEF_VERIFYOBJECTFIELDS
26#include "circt/Dialect/OM/OMPasses.h.inc"
27} // namespace om
28} // namespace circt
29
30using namespace mlir;
31using namespace circt;
32using namespace om;
33
34namespace {
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";
41 }
42};
43} // namespace
44
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>();
51
52 // Run actual verification. Make sure not to mutate `tables`.
53 auto result = mlir::failableParallelForEach(
54 &getContext(), module->getRegion(0).getOps<om::ClassLike>(),
55 [&symbolTable](ClassLike classLike) {
56 auto result =
57 classLike.walk([&](ObjectFieldOp objectField) -> WalkResult {
58 auto objectInstType =
59 cast<ClassType>(objectField.getObject().getType());
60 ClassLike classDef = symbolTable.lookup<ClassLike>(
61 objectInstType.getClassName().getAttr());
62 if (!classDef) {
63 objectField.emitError()
64 << "class " << objectInstType.getClassName()
65 << " was not found";
66 return WalkResult::interrupt();
67 }
68
69 // Traverse the field path, verifying each field exists.
70 Type finalFieldType;
71 auto fields = SmallVector<FlatSymbolRefAttr>(
72 objectField.getFieldPath().getAsRange<FlatSymbolRefAttr>());
73 for (size_t i = 0, e = fields.size(); i < e; ++i) {
74 // Verify the field exists on the ClassOp.
75 auto field = fields[i];
76 std::optional<Type> fieldTypeOpt =
77 classDef.getFieldType(field.getAttr());
78
79 if (!fieldTypeOpt.has_value()) {
80 auto error =
81 objectField.emitOpError("referenced non-existent field ")
82 << field;
83 error.attachNote(classDef.getLoc()) << "class defined here";
84 return WalkResult::interrupt();
85 }
86 Type fieldType = fieldTypeOpt.value();
87
88 // If there are more fields, verify the current field is of
89 // ClassType, and look up the ClassOp for that field.
90 if (i < e - 1) {
91 auto classType = dyn_cast<ClassType>(fieldType);
92 if (!classType) {
93 objectField.emitOpError("nested field access into ")
94 << field << " requires a ClassType, but found "
95 << fieldType;
96 return WalkResult::interrupt();
97 }
98
99 // Check if the nested ClassOp exists. ObjectInstOp verifier
100 // already checked the class exits but it's not verified yet
101 // if the object is an input argument.
102 classDef = symbolTable.lookup<ClassOp>(
103 classType.getClassName().getAttr());
104
105 if (!classDef) {
106 objectField.emitError()
107 << "class " << classType.getClassName()
108 << " was not found";
109 return WalkResult::interrupt();
110 }
111
112 // Proceed to the next field in the path.
113 continue;
114 }
115
116 // On the last iteration down the path, save the final field
117 // being accessed.
118 finalFieldType = fieldType;
119 }
120
121 // Verify the accessed field type matches the result type.
122 if (finalFieldType != objectField.getResult().getType()) {
123 objectField.emitOpError("expected type ")
124 << objectField.getResult().getType()
125 << ", but accessed field has type " << finalFieldType;
126
127 return WalkResult::interrupt();
128 }
129 return WalkResult::advance();
130 });
131 return LogicalResult::failure(result.wasInterrupted());
132 });
133 if (failed(result))
134 return signalPassFailure();
135 return markAllAnalysesPreserved();
136}
137
138std::unique_ptr<mlir::Pass> circt::om::createVerifyObjectFieldsPass() {
139 return std::make_unique<VerifyObjectFieldsPass>();
140}
assert(baseType &&"element must be base type")
std::unique_ptr< mlir::Pass > createVerifyObjectFieldsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition om.py:1