CIRCT 24.0.0git
Loading...
Searching...
No Matches
Evaluator.h
Go to the documentation of this file.
1//===- Evaluator.h - Object Model dialect evaluator -----------------------===//
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// This file contains the Object Model dialect declaration.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CIRCT_DIALECT_OM_EVALUATOR_EVALUATOR_H
14#define CIRCT_DIALECT_OM_EVALUATOR_EVALUATOR_H
15
17#include "circt/Support/LLVM.h"
18#include "mlir/IR/BuiltinOps.h"
19#include "mlir/IR/Diagnostics.h"
20#include "mlir/IR/Location.h"
21#include "mlir/IR/MLIRContext.h"
22#include "mlir/IR/SymbolTable.h"
23#include "mlir/Support/LogicalResult.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/Support/Debug.h"
26
27#include <utility>
28
29namespace circt {
30namespace om {
31
32namespace evaluator {
33class EvaluatorValue;
34
35/// A value of an object in memory. It is either a composite Object, or a
36/// primitive Attribute. Further refinement is expected.
37using EvaluatorValuePtr = std::shared_ptr<EvaluatorValue>;
38
39/// The fields of a composite Object, currently represented as a map. Further
40/// refinement is expected.
42
43/// Base class for evaluator runtime values.
44/// Enables the shared_from_this functionality so Evaluator Value pointers can
45/// be passed through the CAPI and unwrapped back into C++ smart pointers with
46/// the appropriate reference count.
47class EvaluatorValue : public std::enable_shared_from_this<EvaluatorValue> {
48public:
49 // Implement LLVM RTTI.
50 enum class Kind { Attr, Object, List, BasePath, Path };
51 EvaluatorValue(MLIRContext *ctx, Kind kind, Location loc)
52 : kind(kind), ctx(ctx), loc(loc) {}
53 Kind getKind() const { return kind; }
54 MLIRContext *getContext() const { return ctx; }
55
56 // Return true the value is fully evaluated.
57 // Unknown values are considered fully evaluated.
58 bool isFullyEvaluated() const { return fullyEvaluated; }
60 assert(!fullyEvaluated && "should not mark twice");
61 fullyEvaluated = true;
62 }
63
64 /// Return true if the value is unknown (has unknown in its fan-in).
65 /// A value is unknown if it depends on an UnknownValueOp or if any of its
66 /// inputs are unknown. Unknown values propagate through operations.
67 bool isUnknown() const { return unknown; }
68
69 /// Mark this value as unknown.
70 /// This also marks the value as fully evaluated if it isn't already, since
71 /// unknown values are considered fully evaluated. This maintains the
72 /// invariant that unknown implies fullyEvaluated.
73 void markUnknown() {
74 unknown = true;
75 if (!fullyEvaluated)
77 }
78
79 /// Return the associated MLIR context.
80 MLIRContext *getContext() { return ctx; }
81
82 // Return a MLIR type which the value represents.
83 Type getType() const;
84
85 // Return the Location associated with the Value.
86 Location getLoc() const { return loc; }
87 // Set the Location associated with the Value.
88 void setLoc(Location l) { loc = l; }
89 // Set the Location, if it is unknown.
90 void setLocIfUnknown(Location l) {
91 if (isa<UnknownLoc>(loc))
92 loc = l;
93 }
94
95private:
96 const Kind kind;
97 MLIRContext *ctx;
98 Location loc;
99 bool fullyEvaluated = false;
100 bool unknown = false;
101};
102
103/// Values which can be directly representable by MLIR attributes.
105public:
106 Attribute getAttr() const { return attr; }
107 template <typename AttrTy>
108 AttrTy getAs() const {
109 return dyn_cast<AttrTy>(attr);
110 }
111 static bool classof(const EvaluatorValue *e) {
112 return e->getKind() == Kind::Attr;
113 }
114
115 // Set Attribute for partially evaluated case.
116 LogicalResult setAttr(Attribute attr);
117
118 Type getType() const { return type; }
119
120 // Factory methods that create AttributeValue objects
121 static std::shared_ptr<EvaluatorValue> get(Attribute attr,
122 LocationAttr loc = {});
123 static std::shared_ptr<EvaluatorValue> get(Type type, LocationAttr loc = {});
124
125private:
126 // Make AttributeValue constructible only by the factory methods
127 struct PrivateTag {};
128
129 // Constructor that requires a PrivateTag
130 AttributeValue(PrivateTag, Attribute attr, Location loc)
132 type(cast<TypedAttr>(attr).getType()) {
134 }
135
136 // Constructor for partially evaluated AttributeValue
139
140 Attribute attr = {};
141 Type type;
142
143 // Friend declaration for the factory methods
144 friend std::shared_ptr<EvaluatorValue> get(Attribute attr, LocationAttr loc);
145 friend std::shared_ptr<EvaluatorValue> get(Type type, LocationAttr loc);
146};
147
148/// A List which contains variadic length of elements with the same type.
149class ListValue : public EvaluatorValue {
150public:
151 ListValue(om::ListType type, SmallVector<EvaluatorValuePtr> elements,
152 Location loc)
154 elements(std::move(elements)) {
156 }
157
158 void setElements(SmallVector<EvaluatorValuePtr> newElements) {
159 elements = std::move(newElements);
161 }
162
163 // Partially evaluated value.
164 ListValue(om::ListType type, Location loc)
166
167 const auto &getElements() const { return elements; }
168
169 /// Return the type of the value, which is a ListType.
170 om::ListType getListType() const { return type; }
171
172 /// Implement LLVM RTTI.
173 static bool classof(const EvaluatorValue *e) {
174 return e->getKind() == Kind::List;
175 }
176
177private:
178 om::ListType type;
179 SmallVector<EvaluatorValuePtr> elements;
180};
181
182/// A composite Object, which has a type and fields.
184public:
185 ObjectValue(om::ClassLike cls, ObjectFields fields, Location loc)
187 fields(std::move(fields)) {
189 }
190
191 // Partially evaluated value.
192 ObjectValue(om::ClassLike cls, Location loc)
194
195 om::ClassLike getClassOp() const { return cls; }
196 const auto &getFields() const { return fields; }
197
199 fields = std::move(newFields);
201 }
202
203 /// Return the type of the value, which is a ClassType.
204 om::ClassType getObjectType() const {
205 auto clsNonConst = const_cast<om::ClassLike &>(cls);
206 return ClassType::get(clsNonConst.getContext(),
207 FlatSymbolRefAttr::get(clsNonConst.getSymNameAttr()));
208 }
209
210 Type getType() const { return getObjectType(); }
211
212 /// Implement LLVM RTTI.
213 static bool classof(const EvaluatorValue *e) {
214 return e->getKind() == Kind::Object;
215 }
216
217 /// Get a field of the Object by name.
218 FailureOr<EvaluatorValuePtr> getField(StringAttr field);
219 FailureOr<EvaluatorValuePtr> getField(StringRef field) {
220 return getField(StringAttr::get(getContext(), field));
221 }
222
223 /// Get all the field names of the Object.
224 ArrayAttr getFieldNames();
225
226private:
227 om::ClassLike cls;
229};
230
231/// A Basepath value.
233public:
234 BasePathValue(MLIRContext *context);
235
236 /// Create a path value representing a basepath.
237 BasePathValue(om::PathAttr path, Location loc);
238
239 om::PathAttr getPath() const;
240
241 /// Set the basepath which this path is relative to.
242 void setBasepath(const BasePathValue &basepath);
243
244 /// Implement LLVM RTTI.
245 static bool classof(const EvaluatorValue *e) {
246 return e->getKind() == Kind::BasePath;
247 }
248
249private:
250 om::PathAttr path;
251};
252
253/// A Path value.
254class PathValue : public EvaluatorValue {
255public:
256 /// Create a path value representing a regular path.
257 PathValue(om::TargetKindAttr targetKind, om::PathAttr path, StringAttr module,
258 StringAttr ref, StringAttr field, Location loc);
259
260 static PathValue getEmptyPath(Location loc);
261
262 om::TargetKindAttr getTargetKind() const { return targetKind; }
263
264 om::PathAttr getPath() const { return path; }
265
266 StringAttr getModule() const { return module; }
267
268 StringAttr getRef() const { return ref; }
269
270 StringAttr getField() const { return field; }
271
272 StringAttr getAsString() const;
273
274 void setBasepath(const BasePathValue &basepath);
275
276 /// Implement LLVM RTTI.
277 static bool classof(const EvaluatorValue *e) {
278 return e->getKind() == Kind::Path;
279 }
280
281private:
282 om::TargetKindAttr targetKind;
283 om::PathAttr path;
284 StringAttr module;
285 StringAttr ref;
286 StringAttr field;
287};
288
289} // namespace evaluator
290
293
294SmallVector<EvaluatorValuePtr>
296 ArrayRef<Attribute> attributes);
297
298/// An Evaluator, which is constructed with an IR module and can instantiate
299/// Objects. Further refinement is expected.
301public:
302 /// Construct an Evaluator with an IR module.
303 Evaluator(ModuleOp mod);
304
305 /// Instantiate an Object with its class name and actual parameters.
306 FailureOr<evaluator::EvaluatorValuePtr>
307 instantiate(StringAttr className, ArrayRef<EvaluatorValuePtr> actualParams);
308
309 /// Get the Module this Evaluator is built from.
310 mlir::ModuleOp getModule();
311
312 FailureOr<evaluator::EvaluatorValuePtr>
313 getPartiallyEvaluatedValue(Type type, Location loc);
314
315 using ActualParameters = ArrayRef<EvaluatorValuePtr>;
316
317private:
318 FailureOr<evaluator::EvaluatorValuePtr>
319 instantiateImpl(StringAttr className,
320 ArrayRef<EvaluatorValuePtr> actualParams);
321
322 FailureOr<EvaluatorValuePtr>
323 getOrCreateValue(Value value, ActualParameters actualParams, Location loc);
324 /// Evaluate a Value in a Class body according to the small expression grammar
325 /// described in the rationale document. The actual parameters are the values
326 /// supplied at the current instantiation of the Class being evaluated.
327 FailureOr<EvaluatorValuePtr>
328 evaluateValue(Value value, ActualParameters actualParams, Location loc);
329
330 /// Evaluator dispatch functions for the small expression grammar.
331 FailureOr<EvaluatorValuePtr> evaluateParameter(BlockArgument formalParam,
332 ActualParameters actualParams,
333 Location loc);
334
335 FailureOr<EvaluatorValuePtr>
336 evaluateConstant(ConstantOp op, ActualParameters actualParams, Location loc);
337
338 /// Instantiate an Object with its class name and actual parameters.
339 FailureOr<EvaluatorValuePtr>
340 evaluateObjectInstance(StringAttr className, ActualParameters actualParams,
341 Location loc);
342 FailureOr<EvaluatorValuePtr>
343 evaluateElaboratedObject(ElaboratedObjectOp op, ActualParameters actualParams,
344 Location loc);
345 FailureOr<EvaluatorValuePtr> evaluateListCreate(ListCreateOp op,
346 ActualParameters actualParams,
347 Location loc);
348 FailureOr<EvaluatorValuePtr> evaluateListConcat(ListConcatOp op,
349 ActualParameters actualParams,
350 Location loc);
351 FailureOr<evaluator::EvaluatorValuePtr>
352 evaluateBasePathCreate(FrozenBasePathCreateOp op,
353 ActualParameters actualParams, Location loc);
354 FailureOr<evaluator::EvaluatorValuePtr>
355 evaluatePathCreate(FrozenPathCreateOp op, ActualParameters actualParams,
356 Location loc);
357 FailureOr<evaluator::EvaluatorValuePtr>
358 evaluateEmptyPath(FrozenEmptyPathOp op, ActualParameters actualParams,
359 Location loc);
360 FailureOr<evaluator::EvaluatorValuePtr>
361 evaluateUnknownValue(UnknownValueOp op, Location loc);
362
363 FailureOr<evaluator::EvaluatorValuePtr> createUnknownValue(Type type,
364 Location loc);
365
366 /// The symbol table for the IR module the Evaluator was constructed with.
367 /// Used to look up class definitions.
368 SymbolTable symbolTable;
369
370 /// Evaluator value storage for the current instantiation.
371 DenseMap<Value, std::shared_ptr<evaluator::EvaluatorValue>> objects;
372
373#ifndef NDEBUG
374 /// Current nesting depth for debug output indentation.
375 unsigned debugNesting = 0;
376
377 /// RAII helper to increment/decrement debugNesting.
379 unsigned &depth;
380 DebugNesting(unsigned &depth) : depth(depth) { ++depth; }
382 };
383
384 raw_ostream &dbgs(unsigned extra = 0) {
385 return llvm::dbgs().indent(debugNesting * 2 + extra * 2);
386 }
387
388 llvm::indent indent(unsigned extra = 0) {
389 return llvm::indent(debugNesting, 2) + extra;
390 }
391#endif
392};
393
394/// Helper to enable printing objects in Diagnostics.
395static inline mlir::Diagnostic &
396operator<<(mlir::Diagnostic &diag,
397 const evaluator::EvaluatorValue &evaluatorValue) {
398 if (auto *attr = llvm::dyn_cast<evaluator::AttributeValue>(&evaluatorValue))
399 diag << attr->getAttr();
400 else if (auto *object =
401 llvm::dyn_cast<evaluator::ObjectValue>(&evaluatorValue))
402 diag << "Object(" << object->getType() << ")";
403 else if (auto *list = llvm::dyn_cast<evaluator::ListValue>(&evaluatorValue))
404 diag << "List(" << list->getType() << ")";
405 else if (llvm::isa<evaluator::BasePathValue>(&evaluatorValue))
406 diag << "BasePath()";
407 else if (llvm::isa<evaluator::PathValue>(&evaluatorValue))
408 diag << "Path()";
409 else
410 assert(false && "unhandled evaluator value");
411
412 // Add unknown marker if the value is unknown
413 if (evaluatorValue.isUnknown())
414 diag << " [unknown]";
415 return diag;
416}
417
418/// Helper to enable printing objects in Diagnostics.
419static inline mlir::Diagnostic &
420operator<<(mlir::Diagnostic &diag, const EvaluatorValuePtr &evaluatorValue) {
421 return diag << *evaluatorValue.get();
422}
423
424#ifndef NDEBUG
425/// Helper to enable printing objects to raw_ostream (e.g., llvm::dbgs()).
426/// Delegates to the Diagnostic overload via an intermediate string.
427static inline llvm::raw_ostream &
428operator<<(llvm::raw_ostream &os,
429 const evaluator::EvaluatorValue &evaluatorValue) {
430 std::string buf;
431 llvm::raw_string_ostream ss(buf);
432 mlir::Diagnostic diag(UnknownLoc::get(evaluatorValue.getContext()),
433 mlir::DiagnosticSeverity::Note);
434 diag << evaluatorValue;
435 ss << diag;
436 return os << ss.str();
437}
438
439static inline llvm::raw_ostream &
440operator<<(llvm::raw_ostream &os, const EvaluatorValuePtr &evaluatorValue) {
441 if (evaluatorValue)
442 return os << *evaluatorValue.get();
443 return os << "<null>";
444}
445#endif // NDEBUG
446
447} // namespace om
448} // namespace circt
449
450#endif // CIRCT_DIALECT_OM_EVALUATOR_EVALUATOR_H
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
An Evaluator, which is constructed with an IR module and can instantiate Objects.
Definition Evaluator.h:300
FailureOr< evaluator::EvaluatorValuePtr > evaluateBasePathCreate(FrozenBasePathCreateOp op, ActualParameters actualParams, Location loc)
FailureOr< EvaluatorValuePtr > evaluateElaboratedObject(ElaboratedObjectOp op, ActualParameters actualParams, Location loc)
FailureOr< evaluator::EvaluatorValuePtr > evaluateEmptyPath(FrozenEmptyPathOp op, ActualParameters actualParams, Location loc)
SymbolTable symbolTable
The symbol table for the IR module the Evaluator was constructed with.
Definition Evaluator.h:368
FailureOr< evaluator::EvaluatorValuePtr > getPartiallyEvaluatedValue(Type type, Location loc)
FailureOr< EvaluatorValuePtr > evaluateValue(Value value, ActualParameters actualParams, Location loc)
Evaluate a Value in a Class body according to the small expression grammar described in the rationale...
FailureOr< EvaluatorValuePtr > evaluateConstant(ConstantOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for constants.
DenseMap< Value, std::shared_ptr< evaluator::EvaluatorValue > > objects
Evaluator value storage for the current instantiation.
Definition Evaluator.h:371
mlir::ModuleOp getModule()
Get the Module this Evaluator is built from.
ArrayRef< EvaluatorValuePtr > ActualParameters
Definition Evaluator.h:315
FailureOr< evaluator::EvaluatorValuePtr > createUnknownValue(Type type, Location loc)
Create an unknown value of the specified type.
FailureOr< EvaluatorValuePtr > evaluateObjectInstance(StringAttr className, ActualParameters actualParams, Location loc)
Instantiate an Object with its class name and actual parameters.
llvm::indent indent(unsigned extra=0)
Definition Evaluator.h:388
unsigned debugNesting
Current nesting depth for debug output indentation.
Definition Evaluator.h:375
FailureOr< evaluator::EvaluatorValuePtr > evaluateUnknownValue(UnknownValueOp op, Location loc)
Evaluate an unknown value.
raw_ostream & dbgs(unsigned extra=0)
Definition Evaluator.h:384
FailureOr< evaluator::EvaluatorValuePtr > instantiate(StringAttr className, ArrayRef< EvaluatorValuePtr > actualParams)
Instantiate an Object with its class name and actual parameters.
FailureOr< EvaluatorValuePtr > getOrCreateValue(Value value, ActualParameters actualParams, Location loc)
FailureOr< evaluator::EvaluatorValuePtr > instantiateImpl(StringAttr className, ArrayRef< EvaluatorValuePtr > actualParams)
FailureOr< EvaluatorValuePtr > evaluateListCreate(ListCreateOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for List creation.
FailureOr< EvaluatorValuePtr > evaluateListConcat(ListConcatOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for List concatenation.
FailureOr< EvaluatorValuePtr > evaluateParameter(BlockArgument formalParam, ActualParameters actualParams, Location loc)
Evaluator dispatch functions for the small expression grammar.
FailureOr< evaluator::EvaluatorValuePtr > evaluatePathCreate(FrozenPathCreateOp op, ActualParameters actualParams, Location loc)
Values which can be directly representable by MLIR attributes.
Definition Evaluator.h:104
LogicalResult setAttr(Attribute attr)
friend std::shared_ptr< EvaluatorValue > get(Attribute attr, LocationAttr loc)
static bool classof(const EvaluatorValue *e)
Definition Evaluator.h:111
AttributeValue(PrivateTag, Attribute attr, Location loc)
Definition Evaluator.h:130
friend std::shared_ptr< EvaluatorValue > get(Type type, LocationAttr loc)
AttributeValue(PrivateTag, Type type, Location loc)
Definition Evaluator.h:137
static bool classof(const EvaluatorValue *e)
Implement LLVM RTTI.
Definition Evaluator.h:245
void setBasepath(const BasePathValue &basepath)
Set the basepath which this path is relative to.
BasePathValue(om::PathAttr path, Location loc)
Create a path value representing a basepath.
Base class for evaluator runtime values.
Definition Evaluator.h:47
EvaluatorValue(MLIRContext *ctx, Kind kind, Location loc)
Definition Evaluator.h:51
void markUnknown()
Mark this value as unknown.
Definition Evaluator.h:73
MLIRContext * getContext()
Return the associated MLIR context.
Definition Evaluator.h:80
bool isUnknown() const
Return true if the value is unknown (has unknown in its fan-in).
Definition Evaluator.h:67
MLIRContext * getContext() const
Definition Evaluator.h:54
A List which contains variadic length of elements with the same type.
Definition Evaluator.h:149
static bool classof(const EvaluatorValue *e)
Implement LLVM RTTI.
Definition Evaluator.h:173
const auto & getElements() const
Definition Evaluator.h:167
ListValue(om::ListType type, Location loc)
Definition Evaluator.h:164
void setElements(SmallVector< EvaluatorValuePtr > newElements)
Definition Evaluator.h:158
SmallVector< EvaluatorValuePtr > elements
Definition Evaluator.h:179
ListValue(om::ListType type, SmallVector< EvaluatorValuePtr > elements, Location loc)
Definition Evaluator.h:151
om::ListType getListType() const
Return the type of the value, which is a ListType.
Definition Evaluator.h:170
A composite Object, which has a type and fields.
Definition Evaluator.h:183
om::ClassType getObjectType() const
Return the type of the value, which is a ClassType.
Definition Evaluator.h:204
FailureOr< EvaluatorValuePtr > getField(StringAttr field)
Get a field of the Object by name.
const auto & getFields() const
Definition Evaluator.h:196
FailureOr< EvaluatorValuePtr > getField(StringRef field)
Definition Evaluator.h:219
ArrayAttr getFieldNames()
Get all the field names of the Object.
static bool classof(const EvaluatorValue *e)
Implement LLVM RTTI.
Definition Evaluator.h:213
void setFields(llvm::SmallDenseMap< StringAttr, EvaluatorValuePtr > newFields)
Definition Evaluator.h:198
ObjectValue(om::ClassLike cls, Location loc)
Definition Evaluator.h:192
om::ClassLike getClassOp() const
Definition Evaluator.h:195
llvm::SmallDenseMap< StringAttr, EvaluatorValuePtr > fields
Definition Evaluator.h:228
ObjectValue(om::ClassLike cls, ObjectFields fields, Location loc)
Definition Evaluator.h:185
StringAttr getModule() const
Definition Evaluator.h:266
StringAttr StringAttr ref
Definition Evaluator.h:285
StringAttr getAsString() const
om::TargetKindAttr getTargetKind() const
Definition Evaluator.h:262
StringAttr getField() const
Definition Evaluator.h:270
om::TargetKindAttr targetKind
Definition Evaluator.h:282
void setBasepath(const BasePathValue &basepath)
om::PathAttr getPath() const
Definition Evaluator.h:264
static bool classof(const EvaluatorValue *e)
Implement LLVM RTTI.
Definition Evaluator.h:277
static PathValue getEmptyPath(Location loc)
StringAttr getRef() const
Definition Evaluator.h:268
std::shared_ptr< EvaluatorValue > EvaluatorValuePtr
A value of an object in memory.
Definition Evaluator.h:37
evaluator::EvaluatorValuePtr EvaluatorValuePtr
Definition Evaluator.h:292
static mlir::Diagnostic & operator<<(mlir::Diagnostic &diag, const evaluator::EvaluatorValue &evaluatorValue)
Helper to enable printing objects in Diagnostics.
Definition Evaluator.h:396
SmallVector< EvaluatorValuePtr > getEvaluatorValuesFromAttributes(MLIRContext *context, ArrayRef< Attribute > attributes)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition om.py:1
RAII helper to increment/decrement debugNesting.
Definition Evaluator.h:378