CIRCT  18.0.0git
Evaluator.cpp
Go to the documentation of this file.
1 //===- Evaluator.cpp - 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 implements the Object Model dialect Evaluator.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "mlir/IR/BuiltinAttributeInterfaces.h"
15 #include "mlir/IR/Location.h"
16 #include "mlir/IR/SymbolTable.h"
17 #include "llvm/ADT/TypeSwitch.h"
18 #include "llvm/Support/Debug.h"
19 
20 #define DEBUG_TYPE "om-evaluator"
21 
22 using namespace mlir;
23 using namespace circt::om;
24 
25 /// Construct an Evaluator with an IR module.
26 circt::om::Evaluator::Evaluator(ModuleOp mod) : symbolTable(mod) {}
27 
28 /// Get the Module this Evaluator is built from.
30  return cast<ModuleOp>(symbolTable.getOp());
31 }
32 
33 SmallVector<evaluator::EvaluatorValuePtr>
35  ArrayRef<Attribute> attributes) {
36  SmallVector<evaluator::EvaluatorValuePtr> values;
37  values.reserve(attributes.size());
38  for (auto attr : attributes)
39  values.push_back(std::make_shared<evaluator::AttributeValue>(attr));
40  return values;
41 }
42 
44  using namespace evaluator;
45  // Early return if already finalized.
46  if (finalized)
47  return success();
48  // Enable the flag to avoid infinite recursions.
49  finalized = true;
50  assert(isFullyEvaluated());
51  return llvm::TypeSwitch<EvaluatorValue *, LogicalResult>(this)
54  [](auto v) { return v->finalizeImpl(); });
55 }
56 
58  return llvm::TypeSwitch<const EvaluatorValue *, Type>(this)
59  .Case<AttributeValue>([](auto *attr) -> Type {
60  return cast<TypedAttr>(attr->getAttr()).getType();
61  })
62  .Case<ObjectValue>([](auto *object) { return object->getObjectType(); })
63  .Case<ListValue>([](auto *list) { return list->getListType(); })
64  .Case<MapValue>([](auto *map) { return map->getMapType(); })
65  .Case<ReferenceValue>([](auto *ref) { return ref->getValueType(); })
66  .Case<TupleValue>([](auto *tuple) { return tuple->getTupleType(); })
67  .Case<BasePathValue>(
68  [this](auto *tuple) { return FrozenBasePathType::get(ctx); })
69  .Case<PathValue>(
70  [this](auto *tuple) { return FrozenPathType::get(ctx); });
71 }
72 
75  using namespace circt::om::evaluator;
76 
77  return TypeSwitch<mlir::Type, FailureOr<evaluator::EvaluatorValuePtr>>(type)
78  .Case([&](circt::om::MapType type) {
80  std::make_shared<evaluator::MapValue>(type, loc);
81  return success(result);
82  })
83  .Case([&](circt::om::ListType type) {
85  std::make_shared<evaluator::ListValue>(type, loc);
86  return success(result);
87  })
88  .Case([&](mlir::TupleType type) {
90  std::make_shared<evaluator::TupleValue>(type, loc);
91  return success(result);
92  })
93 
94  .Case([&](circt::om::ClassType type)
96  ClassOp cls =
97  symbolTable.lookup<ClassOp>(type.getClassName().getValue());
98  if (!cls)
99  return symbolTable.getOp()->emitError("unknown class name ")
100  << type.getClassName();
101 
103  std::make_shared<evaluator::ObjectValue>(cls, loc);
104 
105  return success(result);
106  })
107  .Default([&](auto type) { return failure(); });
108 }
109 
111  Value value, ActualParameters actualParams, Location loc) {
112  auto it = objects.find({value, actualParams});
113  if (it != objects.end()) {
114  auto evalVal = it->second;
115  evalVal->setLocIfUnknown(loc);
116  return evalVal;
117  }
118 
120  TypeSwitch<Value, FailureOr<evaluator::EvaluatorValuePtr>>(value)
121  .Case([&](BlockArgument arg) {
122  auto val = (*actualParams)[arg.getArgNumber()];
123  val->setLoc(loc);
124  return val;
125  })
126  .Case([&](OpResult result) {
127  return TypeSwitch<Operation *,
129  result.getDefiningOp())
130  .Case([&](ConstantOp op) {
131  return evaluateConstant(op, actualParams, loc);
132  })
133  .Case<ObjectFieldOp>([&](auto op) {
134  // Create a reference value since the value pointed by object
135  // field op is not created yet.
137  std::make_shared<evaluator::ReferenceValue>(
138  value.getType(), loc);
139  return success(result);
140  })
141  .Case<AnyCastOp>([&](AnyCastOp op) {
142  return getOrCreateValue(op.getInput(), actualParams, loc);
143  })
144  .Case<FrozenBasePathCreateOp>([&](FrozenBasePathCreateOp op) {
146  std::make_shared<evaluator::BasePathValue>(
147  op.getPathAttr(), loc);
148  return success(result);
149  })
150  .Case<FrozenPathCreateOp>([&](FrozenPathCreateOp op) {
152  std::make_shared<evaluator::PathValue>(
153  op.getTargetKindAttr(), op.getPathAttr(),
154  op.getModuleAttr(), op.getRefAttr(),
155  op.getFieldAttr(), loc);
156  return success(result);
157  })
158  .Case<FrozenEmptyPathOp>([&](FrozenEmptyPathOp op) {
160  std::make_shared<evaluator::PathValue>(
162  return success(result);
163  })
164  .Case<ListCreateOp, TupleCreateOp, MapCreateOp, ObjectFieldOp,
165  ObjectOp>([&](auto op) {
166  return getPartiallyEvaluatedValue(op.getType(), loc);
167  })
168  .Default([&](Operation *op) {
169  auto error = op->emitError("unable to evaluate value");
170  error.attachNote() << "value: " << value;
171  return error;
172  });
173  });
174  if (failed(result))
175  return result;
176 
177  objects[{value, actualParams}] = result.value();
178  return result;
179 }
180 
183  ActualParameters actualParams,
184  Location loc,
185  ObjectKey instanceKey) {
186  ClassOp cls = symbolTable.lookup<ClassOp>(className);
187  if (!cls)
188  return symbolTable.getOp()->emitError("unknown class name ") << className;
189 
190  auto formalParamNames = cls.getFormalParamNames().getAsRange<StringAttr>();
191  auto formalParamTypes = cls.getBodyBlock()->getArgumentTypes();
192 
193  // Verify the actual parameters are the right size and types for this class.
194  if (actualParams->size() != formalParamTypes.size()) {
195  auto error = cls.emitError("actual parameter list length (")
196  << actualParams->size() << ") does not match formal "
197  << "parameter list length (" << formalParamTypes.size() << ")";
198  auto &diag = error.attachNote() << "actual parameters: ";
199  // FIXME: `diag << actualParams` doesn't work for some reason.
200  bool isFirst = true;
201  for (const auto &param : *actualParams) {
202  if (isFirst)
203  isFirst = false;
204  else
205  diag << ", ";
206  diag << param;
207  }
208  error.attachNote(cls.getLoc()) << "formal parameters: " << formalParamTypes;
209  return error;
210  }
211 
212  // Verify the actual parameter types match.
213  for (auto [actualParam, formalParamName, formalParamType] :
214  llvm::zip(*actualParams, formalParamNames, formalParamTypes)) {
215  if (!actualParam || !actualParam.get())
216  return cls.emitError("actual parameter for ")
217  << formalParamName << " is null";
218 
219  // Subtyping: if formal param is any type, any actual param may be passed.
220  if (isa<AnyType>(formalParamType))
221  continue;
222 
223  Type actualParamType = actualParam->getType();
224 
225  assert(actualParamType && "actualParamType must be non-null!");
226 
227  if (actualParamType != formalParamType) {
228  auto error = cls.emitError("actual parameter for ")
229  << formalParamName << " has invalid type";
230  error.attachNote() << "actual parameter: " << *actualParam;
231  error.attachNote() << "format parameter type: " << formalParamType;
232  return error;
233  }
234  }
235 
236  // Instantiate the fields.
238 
239  auto *context = cls.getContext();
240  for (auto &op : cls.getOps())
241  for (auto result : op.getResults()) {
242  // Allocate the value, with unknown loc. It will be later set when
243  // evaluating the fields.
244  if (failed(
245  getOrCreateValue(result, actualParams, UnknownLoc::get(context))))
246  return failure();
247  // Add to the worklist.
248  worklist.push({result, actualParams});
249  }
250 
251  for (auto field : cls.getOps<ClassFieldOp>()) {
252  StringAttr name = field.getSymNameAttr();
253  Value value = field.getValue();
255  evaluateValue(value, actualParams, field.getLoc());
256  if (failed(result))
257  return result;
258 
259  fields[name] = result.value();
260  }
261 
262  // If the there is an instance, we must update the object value.
263  if (instanceKey.first) {
264  auto result =
265  getOrCreateValue(instanceKey.first, instanceKey.second, loc).value();
266  auto *object = llvm::cast<evaluator::ObjectValue>(result.get());
267  object->setFields(std::move(fields));
268  return result;
269  }
270 
271  // If it's external call, just allocate new ObjectValue.
273  std::make_shared<evaluator::ObjectValue>(cls, fields, loc);
274  return result;
275 }
276 
277 /// Instantiate an Object with its class name and actual parameters.
280  StringAttr className, ArrayRef<evaluator::EvaluatorValuePtr> actualParams) {
281  ClassOp cls = symbolTable.lookup<ClassOp>(className);
282  if (!cls)
283  return symbolTable.getOp()->emitError("unknown class name ") << className;
284 
285  auto parameters =
286  std::make_unique<SmallVector<std::shared_ptr<evaluator::EvaluatorValue>>>(
287  actualParams);
288 
289  actualParametersBuffers.push_back(std::move(parameters));
290 
291  auto loc = cls.getLoc();
292  auto result = evaluateObjectInstance(
293  className, actualParametersBuffers.back().get(), loc);
294 
295  if (failed(result))
296  return failure();
297 
298  // `evaluateObjectInstance` has populated the worklist. Continue evaluations
299  // unless there is a partially evaluated value.
300  while (!worklist.empty()) {
301  auto [value, args] = worklist.front();
302  worklist.pop();
303 
304  auto result = evaluateValue(value, args, loc);
305 
306  if (failed(result))
307  return failure();
308 
309  // It's possible that the value is not fully evaluated.
310  if (!result.value()->isFullyEvaluated())
311  worklist.push({value, args});
312  }
313 
314  auto &object = result.value();
315  // Finalize the value. This will eliminate intermidiate ReferenceValue used as
316  // a placeholder in the initialization.
317  if (failed(object->finalize()))
318  return cls.emitError() << "failed to finalize evaluation. Probably the "
319  "class contains a dataflow cycle";
320  return object;
321 }
322 
325  Location loc) {
326  auto evaluatorValue = getOrCreateValue(value, actualParams, loc).value();
327 
328  // Return if the value is already evaluated.
329  if (evaluatorValue->isFullyEvaluated())
330  return evaluatorValue;
331 
332  return llvm::TypeSwitch<Value, FailureOr<evaluator::EvaluatorValuePtr>>(value)
333  .Case([&](BlockArgument arg) {
334  return evaluateParameter(arg, actualParams, loc);
335  })
336  .Case([&](OpResult result) {
337  return TypeSwitch<Operation *, FailureOr<evaluator::EvaluatorValuePtr>>(
338  result.getDefiningOp())
339  .Case([&](ConstantOp op) {
340  return evaluateConstant(op, actualParams, loc);
341  })
342  .Case([&](ObjectOp op) {
343  return evaluateObjectInstance(op, actualParams);
344  })
345  .Case([&](ObjectFieldOp op) {
346  return evaluateObjectField(op, actualParams, loc);
347  })
348  .Case([&](ListCreateOp op) {
349  return evaluateListCreate(op, actualParams, loc);
350  })
351  .Case([&](TupleCreateOp op) {
352  return evaluateTupleCreate(op, actualParams, loc);
353  })
354  .Case([&](TupleGetOp op) {
355  return evaluateTupleGet(op, actualParams, loc);
356  })
357  .Case([&](AnyCastOp op) {
358  return evaluateValue(op.getInput(), actualParams, loc);
359  })
360  .Case([&](MapCreateOp op) {
361  return evaluateMapCreate(op, actualParams, loc);
362  })
363  .Case([&](FrozenBasePathCreateOp op) {
364  return evaluateBasePathCreate(op, actualParams, loc);
365  })
366  .Case([&](FrozenPathCreateOp op) {
367  return evaluatePathCreate(op, actualParams, loc);
368  })
369  .Case([&](FrozenEmptyPathOp op) {
370  return evaluateEmptyPath(op, actualParams, loc);
371  })
372  .Default([&](Operation *op) {
373  auto error = op->emitError("unable to evaluate value");
374  error.attachNote() << "value: " << value;
375  return error;
376  });
377  });
378 }
379 
380 /// Evaluator dispatch function for parameters.
382  BlockArgument formalParam, ActualParameters actualParams, Location loc) {
383  auto val = (*actualParams)[formalParam.getArgNumber()];
384  val->setLoc(loc);
385  return success(val);
386 }
387 
388 /// Evaluator dispatch function for constants.
391  ActualParameters actualParams,
392  Location loc) {
393  return success(std::make_shared<circt::om::evaluator::AttributeValue>(
394  op.getValue(), loc));
395 }
396 
397 /// Evaluator dispatch function for Object instances.
400  ValueRange range, ActualParameters actualParams, Location loc) {
401  // Create an unique storage to store parameters.
402  auto parameters = std::make_unique<
403  SmallVector<std::shared_ptr<evaluator::EvaluatorValue>>>();
404 
405  // Collect operands' evaluator values in the current instantiation context.
406  for (auto input : range) {
407  auto inputResult = getOrCreateValue(input, actualParams, loc);
408  if (failed(inputResult))
409  return failure();
410  parameters->push_back(inputResult.value());
411  }
412 
413  actualParametersBuffers.push_back(std::move(parameters));
414  return actualParametersBuffers.back().get();
415 }
416 
417 /// Evaluator dispatch function for Object instances.
420  ActualParameters actualParams) {
421  auto loc = op.getLoc();
422  if (isFullyEvaluated({op, actualParams}))
423  return getOrCreateValue(op, actualParams, loc);
424 
425  auto params =
426  createParametersFromOperands(op.getOperands(), actualParams, loc);
427  if (failed(params))
428  return failure();
429  return evaluateObjectInstance(op.getClassNameAttr(), params.value(), loc,
430  {op, actualParams});
431 }
432 
433 /// Evaluator dispatch function for Object fields.
436  ActualParameters actualParams,
437  Location loc) {
438  // Evaluate the Object itself, in case it hasn't been evaluated yet.
439  FailureOr<evaluator::EvaluatorValuePtr> currentObjectResult =
440  evaluateValue(op.getObject(), actualParams, loc);
441  if (failed(currentObjectResult))
442  return currentObjectResult;
443 
444  auto *currentObject =
445  llvm::cast<evaluator::ObjectValue>(currentObjectResult.value().get());
446 
447  auto objectFieldValue = getOrCreateValue(op, actualParams, loc).value();
448 
449  // Iteratively access nested fields through the path until we reach the final
450  // field in the path.
451  evaluator::EvaluatorValuePtr finalField;
452  for (auto field : op.getFieldPath().getAsRange<FlatSymbolRefAttr>()) {
453  // `currentObject` might no be fully evaluated.
454  if (!currentObject->getFields().contains(field.getAttr()))
455  return objectFieldValue;
456 
457  auto currentField = currentObject->getField(field.getAttr());
458  finalField = currentField.value();
459  if (auto *nextObject =
460  llvm::dyn_cast<evaluator::ObjectValue>(finalField.get()))
461  currentObject = nextObject;
462  }
463 
464  // Update the reference.
465  llvm::cast<evaluator::ReferenceValue>(objectFieldValue.get())
466  ->setValue(finalField);
467 
468  // Return the field being accessed.
469  return objectFieldValue;
470 }
471 
472 /// Evaluator dispatch function for List creation.
475  ActualParameters actualParams,
476  Location loc) {
477  // Evaluate the Object itself, in case it hasn't been evaluated yet.
478  SmallVector<evaluator::EvaluatorValuePtr> values;
479  auto list = getOrCreateValue(op, actualParams, loc);
480  for (auto operand : op.getOperands()) {
481  auto result = evaluateValue(operand, actualParams, loc);
482  if (failed(result))
483  return result;
484  if (!result.value()->isFullyEvaluated())
485  return list;
486  values.push_back(result.value());
487  }
488 
489  // Return the list.
490  llvm::cast<evaluator::ListValue>(list.value().get())
491  ->setElements(std::move(values));
492  return list;
493 }
494 
495 /// Evaluator dispatch function for Tuple creation.
498  ActualParameters actualParams,
499  Location loc) {
500  SmallVector<evaluator::EvaluatorValuePtr> values;
501  for (auto operand : op.getOperands()) {
502  auto result = evaluateValue(operand, actualParams, loc);
503  if (failed(result))
504  return result;
505  values.push_back(result.value());
506  }
507 
508  // Return the tuple.
509  auto val = getOrCreateValue(op, actualParams, loc);
510  llvm::cast<evaluator::TupleValue>(val.value().get())
511  ->setElements(std::move(values));
512  return val;
513 }
514 
515 /// Evaluator dispatch function for List creation.
517  TupleGetOp op, ActualParameters actualParams, Location loc) {
518  auto tuple = evaluateValue(op.getInput(), actualParams, loc);
519  if (failed(tuple))
520  return tuple;
522  cast<evaluator::TupleValue>(tuple.value().get())
523  ->getElements()[op.getIndex()];
524  return result;
525 }
526 
527 /// Evaluator dispatch function for Map creation.
529  MapCreateOp op, ActualParameters actualParams, Location loc) {
530  // Evaluate the Object itself, in case it hasn't been evaluated yet.
531  DenseMap<Attribute, evaluator::EvaluatorValuePtr> elements;
532  auto valueResult = getOrCreateValue(op, actualParams, loc).value();
533  for (auto operand : op.getOperands()) {
534  auto result = evaluateValue(operand, actualParams, loc);
535  if (failed(result))
536  return result;
537  // The result is a tuple.
538  auto &value = result.value();
539  if (!value->isFullyEvaluated())
540  return valueResult;
541  const auto &element =
542  llvm::cast<evaluator::TupleValue>(value.get())->getElements();
543  assert(element.size() == 2);
544  auto attr =
545  llvm::cast<evaluator::AttributeValue>(element[0].get())->getAttr();
546  if (!elements.insert({attr, element[1]}).second)
547  return op.emitError() << "map contains duplicated keys";
548  }
549 
550  // Return the Map.
551  llvm::cast<evaluator::MapValue>(valueResult.get())
552  ->setElements(std::move(elements));
553  return valueResult;
554 }
555 
558  ActualParameters actualParams,
559  Location loc) {
560  // Evaluate the Object itself, in case it hasn't been evaluated yet.
561  auto valueResult = getOrCreateValue(op, actualParams, loc).value();
562  auto *path = llvm::cast<evaluator::BasePathValue>(valueResult.get());
563  auto result = evaluateValue(op.getBasePath(), actualParams, loc);
564  if (failed(result))
565  return result;
566  auto &value = result.value();
567  if (!value->isFullyEvaluated())
568  return valueResult;
569  path->setBasepath(*llvm::cast<evaluator::BasePathValue>(value.get()));
570  return valueResult;
571 }
572 
575  ActualParameters actualParams,
576  Location loc) {
577  // Evaluate the Object itself, in case it hasn't been evaluated yet.
578  auto valueResult = getOrCreateValue(op, actualParams, loc).value();
579  auto *path = llvm::cast<evaluator::PathValue>(valueResult.get());
580  auto result = evaluateValue(op.getBasePath(), actualParams, loc);
581  if (failed(result))
582  return result;
583  auto &value = result.value();
584  if (!value->isFullyEvaluated())
585  return valueResult;
586  path->setBasepath(*llvm::cast<evaluator::BasePathValue>(value.get()));
587  return valueResult;
588 }
589 
591  FrozenEmptyPathOp op, ActualParameters actualParams, Location loc) {
592  auto valueResult = getOrCreateValue(op, actualParams, loc).value();
593  return valueResult;
594 }
595 
596 //===----------------------------------------------------------------------===//
597 // ObjectValue
598 //===----------------------------------------------------------------------===//
599 
600 /// Get a field of the Object by name.
603  auto field = fields.find(name);
604  if (field == fields.end())
605  return cls.emitError("field ") << name << " does not exist";
606  return success(fields[name]);
607 }
608 
609 /// Get an ArrayAttr with the names of the fields in the Object. Sort the fields
610 /// so there is always a stable order.
612  SmallVector<Attribute> fieldNames;
613  for (auto &f : fields)
614  fieldNames.push_back(f.first);
615 
616  llvm::sort(fieldNames, [](Attribute a, Attribute b) {
617  return cast<StringAttr>(a).getValue() < cast<StringAttr>(b).getValue();
618  });
619 
620  return ArrayAttr::get(cls.getContext(), fieldNames);
621 }
622 
624  for (auto &&[e, value] : fields)
625  if (failed(finalizeEvaluatorValue(value)))
626  return failure();
627 
628  return success();
629 }
630 
631 //===----------------------------------------------------------------------===//
632 // MapValue
633 //===----------------------------------------------------------------------===//
634 
635 /// Return an array of keys in the ascending order.
637  SmallVector<Attribute> attrs;
638  for (auto &[key, _] : elements)
639  attrs.push_back(key);
640 
641  std::sort(attrs.begin(), attrs.end(), [](Attribute l, Attribute r) {
642  if (auto lInt = dyn_cast<mlir::IntegerAttr>(l))
643  if (auto rInt = dyn_cast<mlir::IntegerAttr>(r))
644  return lInt.getValue().ult(rInt.getValue());
645 
646  assert(isa<StringAttr>(l) && isa<StringAttr>(r) &&
647  "key type should be integer or string");
648  return cast<StringAttr>(l).getValue() < cast<StringAttr>(r).getValue();
649  });
650 
651  return ArrayAttr::get(type.getContext(), attrs);
652 }
653 
655  for (auto &&[e, value] : elements)
656  if (failed(finalizeEvaluatorValue(value)))
657  return failure();
658  return success();
659 }
660 
661 //===----------------------------------------------------------------------===//
662 // ReferenceValue
663 //===----------------------------------------------------------------------===//
664 
666  auto result = getStrippedValue();
667  if (failed(result))
668  return result;
669  value = std::move(result.value());
670  return success();
671 }
672 
673 //===----------------------------------------------------------------------===//
674 // ListValue
675 //===----------------------------------------------------------------------===//
676 
678  for (auto &value : elements) {
679  if (failed(finalizeEvaluatorValue(value)))
680  return failure();
681  }
682  return success();
683 }
684 
685 //===----------------------------------------------------------------------===//
686 // BasePathValue
687 //===----------------------------------------------------------------------===//
688 
690  : EvaluatorValue(context, Kind::BasePath, UnknownLoc::get(context)),
691  path(PathAttr::get(context, {})) {
692  markFullyEvaluated();
693 }
694 
695 evaluator::BasePathValue::BasePathValue(PathAttr path, Location loc)
696  : EvaluatorValue(path.getContext(), Kind::BasePath, loc), path(path) {}
697 
699  assert(isFullyEvaluated());
700  return path;
701 }
702 
704  assert(!isFullyEvaluated());
705  auto newPath = llvm::to_vector(basepath.path.getPath());
706  auto oldPath = path.getPath();
707  newPath.append(oldPath.begin(), oldPath.end());
708  path = PathAttr::get(path.getContext(), newPath);
709  markFullyEvaluated();
710 }
711 
712 //===----------------------------------------------------------------------===//
713 // PathValue
714 //===----------------------------------------------------------------------===//
715 
716 evaluator::PathValue::PathValue(TargetKindAttr targetKind, PathAttr path,
717  StringAttr module, StringAttr ref,
718  StringAttr field, Location loc)
719  : EvaluatorValue(loc.getContext(), Kind::Path, loc), targetKind(targetKind),
720  path(path), module(module), ref(ref), field(field) {}
721 
723  PathValue path(nullptr, nullptr, nullptr, nullptr, nullptr, loc);
724  path.markFullyEvaluated();
725  return path;
726 }
727 
729  // If the module is null, then this is a path to a deleted object.
730  if (!targetKind)
731  return StringAttr::get(getContext(), "OMDeleted");
732  SmallString<64> result;
733  switch (targetKind.getValue()) {
734  case TargetKind::DontTouch:
735  result += "OMDontTouchedReferenceTarget";
736  break;
737  case TargetKind::Instance:
738  result += "OMInstanceTarget";
739  break;
740  case TargetKind::MemberInstance:
741  result += "OMMemberInstanceTarget";
742  break;
743  case TargetKind::MemberReference:
744  result += "OMMemberReferenceTarget";
745  break;
746  case TargetKind::Reference:
747  result += "OMReferenceTarget";
748  break;
749  }
750  result += ":~";
751  if (!path.getPath().empty())
752  result += path.getPath().front().module;
753  else
754  result += module.getValue();
755  result += '|';
756  for (const auto &elt : path) {
757  result += elt.module.getValue();
758  result += '/';
759  result += elt.instance.getValue();
760  result += ':';
761  }
762  if (!module.getValue().empty())
763  result += module.getValue();
764  if (!ref.getValue().empty()) {
765  result += '>';
766  result += ref.getValue();
767  }
768  if (!field.getValue().empty())
769  result += field.getValue();
770  return StringAttr::get(field.getContext(), result);
771 }
772 
774  assert(!isFullyEvaluated());
775  auto newPath = llvm::to_vector(basepath.getPath().getPath());
776  auto oldPath = path.getPath();
777  newPath.append(oldPath.begin(), oldPath.end());
778  path = PathAttr::get(path.getContext(), newPath);
779  markFullyEvaluated();
780 }
lowerAnnotationsNoRefTypePorts FirtoolPreserveValuesMode value
Definition: Firtool.cpp:95
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:53
static LogicalResult finalizeEvaluatorValue(EvaluatorValuePtr &value)
Definition: Evaluator.h:158
std::shared_ptr< EvaluatorValue > EvaluatorValuePtr
A value of an object in memory.
Definition: Evaluator.h:38
SmallVector< EvaluatorValuePtr > getEvaluatorValuesFromAttributes(MLIRContext *context, ArrayRef< Attribute > attributes)
Definition: Evaluator.cpp:34
FailureOr< evaluator::EvaluatorValuePtr > evaluateBasePathCreate(FrozenBasePathCreateOp op, ActualParameters actualParams, Location loc)
Definition: Evaluator.cpp:557
FailureOr< evaluator::EvaluatorValuePtr > evaluateEmptyPath(FrozenEmptyPathOp op, ActualParameters actualParams, Location loc)
Definition: Evaluator.cpp:590
FailureOr< evaluator::EvaluatorValuePtr > getPartiallyEvaluatedValue(Type type, Location loc)
Definition: Evaluator.cpp:74
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...
Definition: Evaluator.cpp:324
FailureOr< EvaluatorValuePtr > evaluateConstant(ConstantOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for constants.
Definition: Evaluator.cpp:390
mlir::ModuleOp getModule()
Get the Module this Evaluator is built from.
Definition: Evaluator.cpp:29
FailureOr< EvaluatorValuePtr > evaluateObjectField(ObjectFieldOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for Object fields.
Definition: Evaluator.cpp:435
Evaluator(ModuleOp mod)
Construct an Evaluator with an IR module.
Definition: Evaluator.cpp:26
FailureOr< evaluator::EvaluatorValuePtr > evaluateMapCreate(MapCreateOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for Map creation.
Definition: Evaluator.cpp:528
FailureOr< evaluator::EvaluatorValuePtr > instantiate(StringAttr className, ArrayRef< EvaluatorValuePtr > actualParams)
Instantiate an Object with its class name and actual parameters.
Definition: Evaluator.cpp:279
FailureOr< EvaluatorValuePtr > getOrCreateValue(Value value, ActualParameters actualParams, Location loc)
Definition: Evaluator.cpp:110
SmallVectorImpl< std::shared_ptr< evaluator::EvaluatorValue > > * ActualParameters
Definition: Evaluator.h:423
FailureOr< EvaluatorValuePtr > evaluateListCreate(ListCreateOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for List creation.
Definition: Evaluator.cpp:474
std::pair< Value, ActualParameters > ObjectKey
Definition: Evaluator.h:425
FailureOr< EvaluatorValuePtr > evaluateParameter(BlockArgument formalParam, ActualParameters actualParams, Location loc)
Evaluator dispatch functions for the small expression grammar.
Definition: Evaluator.cpp:381
FailureOr< EvaluatorValuePtr > evaluateObjectInstance(StringAttr className, ActualParameters actualParams, Location loc, ObjectKey instanceKey={})
Instantiate an Object with its class name and actual parameters.
Definition: Evaluator.cpp:182
FailureOr< EvaluatorValuePtr > evaluateTupleGet(TupleGetOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for List creation.
Definition: Evaluator.cpp:516
FailureOr< EvaluatorValuePtr > evaluateTupleCreate(TupleCreateOp op, ActualParameters actualParams, Location loc)
Evaluator dispatch function for Tuple creation.
Definition: Evaluator.cpp:497
FailureOr< evaluator::EvaluatorValuePtr > evaluatePathCreate(FrozenPathCreateOp op, ActualParameters actualParams, Location loc)
Definition: Evaluator.cpp:574
FailureOr< ActualParameters > createParametersFromOperands(ValueRange range, ActualParameters actualParams, Location loc)
Evaluator dispatch function for Object instances.
Definition: Evaluator.cpp:399
Values which can be directly representable by MLIR attributes.
Definition: Evaluator.h:132
BasePathValue(MLIRContext *context)
Definition: Evaluator.cpp:689
void setBasepath(const BasePathValue &basepath)
Set the basepath which this path is relative to.
Definition: Evaluator.cpp:703
Base class for evaluator runtime values.
Definition: Evaluator.h:48
A List which contains variadic length of elements with the same type.
Definition: Evaluator.h:171
ArrayAttr getKeys()
Return an array of keys in the ascending order.
Definition: Evaluator.cpp:636
A composite Object, which has a type and fields.
Definition: Evaluator.h:245
FailureOr< EvaluatorValuePtr > getField(StringAttr field)
Get a field of the Object by name.
Definition: Evaluator.cpp:602
ArrayAttr getFieldNames()
Get all the field names of the Object.
Definition: Evaluator.cpp:611
StringAttr getAsString() const
Definition: Evaluator.cpp:728
void setBasepath(const BasePathValue &basepath)
Definition: Evaluator.cpp:773
PathValue(om::TargetKindAttr targetKind, om::PathAttr path, StringAttr module, StringAttr ref, StringAttr field, Location loc)
Create a path value representing a regular path.
Definition: Evaluator.cpp:716
static PathValue getEmptyPath(Location loc)
Definition: Evaluator.cpp:722
Values which can be used as pointers to different values.
Definition: Evaluator.h:93