15#include "mlir/IR/Builders.h"
16#include "mlir/IR/BuiltinAttributeInterfaces.h"
17#include "mlir/IR/Location.h"
18#include "mlir/IR/SymbolTable.h"
19#include "mlir/IR/Verifier.h"
20#include "mlir/Pass/PassManager.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/ScopeExit.h"
23#include "llvm/ADT/TypeSwitch.h"
24#include "llvm/ADT/iterator_range.h"
25#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "om-evaluator"
34LogicalResult verifyActualParameters(ClassLike classLike,
35 ArrayRef<EvaluatorValuePtr> actualParams) {
36 auto formalParamNames =
37 classLike.getFormalParamNames().getAsRange<StringAttr>();
38 auto formalParamTypes = classLike.getBodyBlock()->getArgumentTypes();
40 if (actualParams.size() != formalParamTypes.size()) {
41 auto error = classLike.emitError(
"actual parameter list length (")
42 << actualParams.size() <<
") does not match formal "
43 <<
"parameter list length (" << formalParamTypes.size() <<
")";
44 auto &diag = error.attachNote() <<
"actual parameters: ";
46 for (
const auto ¶m : actualParams) {
53 error.attachNote(classLike.getLoc())
54 <<
"formal parameters: " << formalParamTypes;
58 for (
auto [actualParam, formalParamName, formalParamType] :
59 llvm::zip(actualParams, formalParamNames, formalParamTypes)) {
60 if (!actualParam || !actualParam.get())
61 return classLike.emitError(
"actual parameter for ")
62 << formalParamName <<
" is null";
65 if (isa<AnyType>(formalParamType))
68 Type actualParamType = actualParam->getType();
69 assert(actualParamType &&
"actualParamType must be non-null!");
71 if (actualParamType != formalParamType) {
72 auto error = classLike.emitError(
"actual parameter for ")
73 << formalParamName <<
" has invalid type";
74 error.attachNote() <<
"actual parameter: " << *actualParam;
75 error.attachNote() <<
"format parameter type: " << formalParamType;
85class ScratchIRBuilder {
87 struct InstantiationInfo {
89 SmallVector<EvaluatorValuePtr> actualParams;
92 ScratchIRBuilder(ModuleOp module, SymbolTable &symbolTable,
94 : module(module), symbolTable(symbolTable), rootClass(rootClass),
95 wrapperClass(createWrapperClass(rootClass)) {}
97 FailureOr<InstantiationInfo> run(ArrayRef<EvaluatorValuePtr> actualParams);
101 ClassOp createWrapperClass(ClassLike rootClass);
106 Location loc, Type expectedType);
118 SymbolTable &symbolTable;
120 ClassOp wrapperClass;
123 DenseMap<evaluator::EvaluatorValue *, Value> importedValues;
127 SmallPtrSet<evaluator::ObjectValue *, 8> activeObjectImports;
129 SmallVector<Attribute> wrapperArgNames;
130 SmallVector<EvaluatorValuePtr> wrapperActualParams;
133FailureOr<ScratchIRBuilder::InstantiationInfo>
134ScratchIRBuilder::run(ArrayRef<EvaluatorValuePtr> actualParams) {
135 auto *ctx =
module.getContext();
136 assert(rootClass &&
"root class must be resolved before building scratch IR");
137 auto rootLoc = rootClass.getLoc();
138 auto rootClassName = rootClass.getSymNameAttr();
140 OpBuilder builder(wrapperClass.getFieldsOp());
141 builder.setInsertionPoint(wrapperClass.getFieldsOp());
142 SmallVector<Value> importedActualValues;
143 importedActualValues.reserve(actualParams.size());
144 auto formalTypes = rootClass.getBodyBlock()->getArgumentTypes();
145 for (
auto [actual, expectedType] : llvm::zip(actualParams, formalTypes)) {
146 auto imported = materializeInput(actual, rootLoc, expectedType);
147 if (failed(imported))
149 importedActualValues.push_back(*imported);
153 wrapperClass->setAttr(wrapperClass.getFormalParamNamesAttrName(),
154 builder.getArrayAttr(wrapperArgNames));
156 wrapperClass.updateFields(
160 ClassType::get(ctx, FlatSymbolRefAttr::get(rootClassName)),
161 rootClassName, importedActualValues)
163 {builder.getStringAttr(
"root")});
165 if (failed(verify(module)))
169 ElaborateObjectOptions options;
170 auto wrapperName = wrapperClass.getSymNameAttr();
171 options.targetClass = wrapperName.getValue().str();
172 pm.addPass(createElaborateObject(std::move(options)));
173 if (failed(pm.run(module)))
176 return InstantiationInfo{wrapperName, std::move(wrapperActualParams)};
179ClassOp ScratchIRBuilder::createWrapperClass(ClassLike rootClass) {
180 OpBuilder builder(module.getBody(), module.getBody()->end());
181 builder.setInsertionPointToEnd(module.getBody());
183 auto wrapper = ClassOp::create(builder, rootClass.getLoc(),
184 Twine(
"__om_evaluator_wrapper_") +
185 rootClass.getSymName());
186 (void)symbolTable.insert(wrapper);
187 Block *body = &wrapper.getBody().emplaceBlock();
188 builder.setInsertionPointToEnd(body);
189 ClassFieldsOp::create(builder, rootClass.getLoc(), ValueRange(), ArrayAttr{});
197 return emitError(loc,
"cannot materialize null OM evaluator value");
199 loc = value->getLoc();
201 return emitError(loc,
"cannot import OM evaluator value without an "
205 if (isa<AnyType>(expectedType))
206 return createWrapperArgument(value, loc, expectedType);
208 if (
auto it = importedValues.find(value.get()); it != importedValues.end())
211 if (value->isUnknown()) {
212 OpBuilder builder(wrapperClass.getFieldsOp());
213 auto result = UnknownValueOp::create(builder, loc, expectedType);
214 importedValues[value.get()] = result.getResult();
215 return result.getResult();
218 return llvm::TypeSwitch<evaluator::EvaluatorValue *, FailureOr<Value>>(
221 auto attr = attrValue->
getAttr();
223 return emitError(loc,
"cannot import OM attribute value without an "
226 OpBuilder builder(wrapperClass.getFieldsOp());
227 auto result = ConstantOp::create(builder, loc, cast<TypedAttr>(attr));
228 importedValues[value.get()] = result.getResult();
229 return result.getResult();
232 return materializeListInput(listValue, loc);
235 return materializeObjectInput(objectValue, loc);
238 auto result = createWrapperArgument(value, loc, expectedType);
239 if (succeeded(result))
240 importedValues[value.get()] = *result;
249 return emitError(loc,
"cannot import partially evaluated OM list value");
252 SmallVector<Value> elementValues;
253 elementValues.reserve(listValue->
getElements().size());
254 for (
const auto &elementValue : listValue->
getElements()) {
255 auto materializedElement =
256 materializeInput(elementValue, loc, listType.getElementType());
257 if (failed(materializedElement))
259 elementValues.push_back(*materializedElement);
262 OpBuilder builder(wrapperClass.getFieldsOp());
263 auto result = ListCreateOp::create(builder, loc, listType, elementValues);
264 importedValues[listValue] = result.getResult();
265 return result.getResult();
275 if (!activeObjectImports.insert(objectValue).second)
276 return emitError(loc,
"cannot import mutually referential OM objects");
278 llvm::scope_exit popActiveObjectImport(
279 [&] { activeObjectImports.erase(objectValue); });
282 SmallVector<Value> fieldValues;
283 auto fieldNames = classLike.getFieldNames();
284 fieldValues.reserve(fieldNames.size());
285 for (
auto fieldName : fieldNames) {
286 auto fieldNameAttr = cast<StringAttr>(fieldName);
287 auto field = objectValue->
getField(fieldNameAttr);
290 auto materializedField = materializeInput(
291 field.value(), loc, classLike.getFieldType(fieldNameAttr).value());
292 if (failed(materializedField))
294 fieldValues.push_back(*materializedField);
297 OpBuilder builder(wrapperClass.getFieldsOp());
299 ElaboratedObjectOp::create(builder, loc, classLike, fieldValues);
300 importedValues[objectValue] = result.getResult();
301 return result.getResult();
307 Builder builder(module.getContext());
308 wrapperArgNames.push_back(
309 builder.getStringAttr(Twine(
"arg") + Twine(wrapperArgNames.size())));
310 wrapperActualParams.push_back(value);
311 return wrapperClass.getBodyBlock()->addArgument(argType, loc);
321 return cast<ModuleOp>(symbolTable.getOp());
324SmallVector<evaluator::EvaluatorValuePtr>
326 ArrayRef<Attribute> attributes) {
327 SmallVector<evaluator::EvaluatorValuePtr> values;
328 values.reserve(attributes.size());
329 for (
auto attr : attributes)
335 return llvm::TypeSwitch<const EvaluatorValue *, Type>(
this)
336 .Case<
AttributeValue>([](
auto *attr) -> Type {
return attr->getType(); })
337 .Case<ObjectValue>([](
auto *
object) {
return object->getObjectType(); })
338 .Case<ListValue>([](
auto *list) {
return list->getListType(); })
339 .Case<BasePathValue>(
340 [
this](
auto *tuple) {
return FrozenBasePathType::get(ctx); })
342 [
this](
auto *tuple) {
return FrozenPathType::get(ctx); });
345FailureOr<evaluator::EvaluatorValuePtr>
350 TypeSwitch<mlir::Type, FailureOr<evaluator::EvaluatorValuePtr>>(type)
351 .Case([&](circt::om::ListType type) {
353 std::make_shared<evaluator::ListValue>(type, loc);
354 return success(result);
356 .Case([&](circt::om::ClassType type)
357 -> FailureOr<evaluator::EvaluatorValuePtr> {
359 symbolTable.lookup<ClassLike>(type.getClassName().getValue());
361 return symbolTable.getOp()->emitError(
"unknown class name ")
362 << type.getClassName();
366 std::make_shared<evaluator::ObjectValue>(classDef, loc);
368 return success(result);
370 .Case([&](circt::om::StringType type) {
373 return success(result);
375 .Default([&](
auto type) {
return failure(); });
382 LLVM_DEBUG(dbgs() <<
"- get: " << value <<
"\n");
384 auto it = objects.find(value);
385 if (it != objects.end()) {
386 auto evalVal = it->second;
387 evalVal->setLocIfUnknown(loc);
391 FailureOr<evaluator::EvaluatorValuePtr> result =
392 TypeSwitch<Value, FailureOr<evaluator::EvaluatorValuePtr>>(value)
393 .Case([&](BlockArgument arg) {
394 return evaluateParameter(arg, actualParams, loc);
396 .Case([&](OpResult result) {
397 return TypeSwitch<Operation *,
398 FailureOr<evaluator::EvaluatorValuePtr>>(
399 result.getDefiningOp())
400 .Case([&](ConstantOp op) {
401 return evaluateConstant(op, actualParams, loc);
403 .Case<AnyCastOp>([&](AnyCastOp op) {
404 return getOrCreateValue(op.getInput(), actualParams, loc);
406 .Case<FrozenBasePathCreateOp>([&](FrozenBasePathCreateOp op) {
408 std::make_shared<evaluator::BasePathValue>(
409 op.getPathAttr(), loc);
410 return success(result);
412 .Case<FrozenPathCreateOp>([&](FrozenPathCreateOp op) {
414 std::make_shared<evaluator::PathValue>(
415 op.getTargetKindAttr(), op.getPathAttr(),
416 op.getModuleAttr(), op.getRefAttr(),
417 op.getFieldAttr(), loc);
418 return success(result);
420 .Case<FrozenEmptyPathOp>([&](FrozenEmptyPathOp op) {
422 std::make_shared<evaluator::PathValue>(
424 return success(result);
426 .Case<ListCreateOp, ListConcatOp>([&](
auto op) {
427 return getPartiallyEvaluatedValue(op.getType(), loc);
429 .Case<ElaboratedObjectOp>([&](
auto op) {
430 return getPartiallyEvaluatedValue(op.getType(), op.getLoc());
432 .Case<UnknownValueOp>(
433 [&](
auto op) {
return evaluateUnknownValue(op, loc); })
434 .Default([&](Operation *op) {
435 auto error = op->emitError(
"unable to evaluate value");
436 error.attachNote() <<
"value: " << value;
443 objects[value] = result.value();
447FailureOr<evaluator::EvaluatorValuePtr>
454 LLVM_DEBUG(dbgs() <<
"object:\n");
458 LLVM_DEBUG(dbgs() <<
"name: " << className <<
"\n");
460 auto classDef = symbolTable.lookup<ClassLike>(className);
462 return symbolTable.getOp()->emitError(
"unknown class name ") << className;
465 if (isa<ClassExternOp>(classDef)) {
467 std::make_shared<evaluator::ObjectValue>(classDef, loc);
468 result->markUnknown();
469 LLVM_DEBUG(dbgs(1) <<
"extern: <unknown-value>\n");
474 ClassOp cls = cast<ClassOp>(classDef);
476 if (failed(verifyActualParameters(cls, actualParams)))
482 auto *
context = cls.getContext();
484 LLVM_DEBUG(dbgs() <<
"ops:\n");
491 for (
auto &op : cls.getOps())
492 for (
auto result : op.getResults())
493 if (failed(getOrCreateValue(result, actualParams,
498 for (
auto &op : cls.getOps())
499 for (
auto result : op.getResults()) {
500 auto evaluated = evaluateValue(result, actualParams, op.getLoc());
501 if (failed(evaluated))
506 LLVM_DEBUG(dbgs() <<
"fields:\n");
507 auto fieldNames = cls.getFieldNames();
508 auto operands = cls.getFieldsOp()->getOperands();
509 for (
size_t i = 0; i < fieldNames.size(); ++i) {
510 auto name = fieldNames[i];
511 auto value = operands[i];
512 auto fieldLoc = cls.getFieldLocByIndex(i);
513 LLVM_DEBUG(dbgs() <<
"- name: " << name <<
"\n"
514 << indent(1) <<
"evaluate:\n");
518 FailureOr<evaluator::EvaluatorValuePtr> result =
519 evaluateValue(value, actualParams, fieldLoc);
523 LLVM_DEBUG(dbgs() <<
"value: " << result.value() <<
"\n");
524 fields[cast<StringAttr>(name)] = result.value();
529 std::make_shared<evaluator::ObjectValue>(cls, fields, loc);
531 assert(result->isFullyEvaluated() &&
532 "object with fields should be fully evaluated");
537FailureOr<std::shared_ptr<evaluator::EvaluatorValue>>
539 StringAttr className, ArrayRef<evaluator::EvaluatorValuePtr> actualParams) {
540 LLVM_DEBUG(dbgs() <<
"instantiate:\n");
545 dbgs() <<
"class: " << className <<
"\n" << indent() <<
"params:\n";
546 for (
auto ¶m : actualParams)
547 dbgs() <<
"- " << param <<
"\n";
550 auto rootClass = symbolTable.lookup<ClassLike>(className);
552 return symbolTable.getOp()->emitError(
"unknown class name ") << className;
553 if (failed(verifyActualParameters(rootClass, actualParams)))
556 ScratchIRBuilder scratchBuilder(getModule(), symbolTable, rootClass);
557 auto transformedInstantiation = scratchBuilder.run(actualParams);
558 if (failed(transformedInstantiation))
561 auto wrapper = instantiateImpl(transformedInstantiation->className,
562 transformedInstantiation->actualParams);
567 cast<evaluator::ObjectValue>(wrapper.value().get())->getField(
"root");
573FailureOr<std::shared_ptr<evaluator::EvaluatorValue>>
575 StringAttr className, ArrayRef<evaluator::EvaluatorValuePtr> actualParams) {
576 auto classDef = symbolTable.lookup<ClassLike>(className);
578 return symbolTable.getOp()->emitError(
"unknown class name ") << className;
581 if (isa<ClassExternOp>(classDef)) {
583 std::make_shared<evaluator::ObjectValue>(
584 classDef, UnknownLoc::get(classDef.getContext()));
585 result->markUnknown();
586 LLVM_DEBUG(dbgs(1) <<
"result: <unknown extern>\n");
591 ClassOp cls = cast<ClassOp>(classDef);
593 auto loc = cls.getLoc();
594 LLVM_DEBUG(dbgs() <<
"evaluate object:\n");
595 auto result = evaluateObjectInstance(className, actualParams, loc);
600 LLVM_DEBUG(dbgs() <<
"result: " << result.value() <<
"\n");
604FailureOr<evaluator::EvaluatorValuePtr>
607 auto evaluatorValue = getOrCreateValue(value, actualParams, loc).value();
609 LLVM_DEBUG(dbgs() <<
"- eval: " << value <<
"\n");
612 if (evaluatorValue->isFullyEvaluated()) {
613 LLVM_DEBUG(dbgs(1) <<
"fully evaluated: " << evaluatorValue <<
"\n");
614 return evaluatorValue;
617 return llvm::TypeSwitch<Value, FailureOr<evaluator::EvaluatorValuePtr>>(value)
618 .Case([&](BlockArgument arg) {
619 return evaluateParameter(arg, actualParams, loc);
621 .Case([&](OpResult result) {
622 return TypeSwitch<Operation *, FailureOr<evaluator::EvaluatorValuePtr>>(
623 result.getDefiningOp())
624 .Case([&](ConstantOp op) {
625 return evaluateConstant(op, actualParams, loc);
627 .Case([&](ElaboratedObjectOp op) {
628 return evaluateElaboratedObject(op, actualParams, loc);
630 .Case([&](ListCreateOp op) {
631 return evaluateListCreate(op, actualParams, loc);
633 .Case([&](ListConcatOp op) {
634 return evaluateListConcat(op, actualParams, loc);
636 .Case([&](AnyCastOp op) {
637 return evaluateValue(op.getInput(), actualParams, loc);
639 .Case([&](FrozenBasePathCreateOp op) {
640 return evaluateBasePathCreate(op, actualParams, loc);
642 .Case([&](FrozenPathCreateOp op) {
643 return evaluatePathCreate(op, actualParams, loc);
645 .Case([&](FrozenEmptyPathOp op) {
646 return evaluateEmptyPath(op, actualParams, loc);
648 .Case<UnknownValueOp>([&](UnknownValueOp op) {
649 return evaluateUnknownValue(op, loc);
651 .Default([&](Operation *op) {
652 auto error = op->emitError(
"unable to evaluate value");
653 error.attachNote() <<
"value: " << value;
662 auto val = actualParams[formalParam.getArgNumber()];
668FailureOr<circt::om::evaluator::EvaluatorValuePtr>
676FailureOr<evaluator::EvaluatorValuePtr>
680 auto objectValue = getOrCreateValue(op, actualParams, loc);
681 if (failed(objectValue))
683 auto object = cast<evaluator::ObjectValue>(objectValue.value().get());
684 if (object->isFullyEvaluated())
688 symbolTable.lookup<ClassLike>(op.getClassNameAttr().getAttr());
690 return symbolTable.getOp()->emitError(
"unknown class name ")
691 << op.getClassNameAttr();
693 auto fieldNames = classLike.getFieldNames();
694 auto fieldValues = op.getFieldValues();
695 if (fieldNames.size() != fieldValues.size())
696 return op.emitError(
"field value list doesn't match class field list, "
698 << fieldNames.size() <<
" values but got " << fieldValues.size();
701 auto classOp = dyn_cast<ClassOp>(classLike.getOperation());
702 for (
auto [index, fieldNameAndValue] :
703 llvm::enumerate(llvm::zip(fieldNames, fieldValues))) {
704 auto [fieldName, fieldValue] = fieldNameAndValue;
705 auto fieldLoc = classOp ? classOp.getFieldLocByIndex(index) : loc;
706 auto fieldResult = getOrCreateValue(fieldValue, actualParams, fieldLoc);
707 if (failed(fieldResult))
710 fields[cast<StringAttr>(fieldName)] = fieldResult.value();
713 object->setFields(std::move(fields));
718FailureOr<evaluator::EvaluatorValuePtr>
723 SmallVector<evaluator::EvaluatorValuePtr> values;
724 auto list = getOrCreateValue(op, actualParams, loc);
725 bool hasUnknown =
false;
726 for (
auto operand : op.getOperands()) {
727 auto result = evaluateValue(operand, actualParams, loc);
730 if (!result.value()->isFullyEvaluated())
733 if (result.value()->isUnknown())
735 values.push_back(result.value());
739 llvm::cast<evaluator::ListValue>(list.value().get())
740 ->setElements(std::move(values));
746 list.value()->markUnknown();
752FailureOr<evaluator::EvaluatorValuePtr>
757 SmallVector<evaluator::EvaluatorValuePtr> values;
758 auto list = getOrCreateValue(op, actualParams, loc);
760 bool hasUnknown =
false;
761 for (
auto operand : op.getOperands()) {
762 auto result = evaluateValue(operand, actualParams, loc);
765 if (!result.value()->isFullyEvaluated())
768 if (result.value()->isUnknown())
771 auto *subList = llvm::cast<evaluator::ListValue>(result.value().get());
774 for (
const auto &subValue : subList->getElements())
775 values.push_back(subValue);
779 llvm::cast<evaluator::ListValue>(list.value().get())
780 ->setElements(std::move(values));
786 list.value()->markUnknown();
791FailureOr<evaluator::EvaluatorValuePtr>
796 auto valueResult = getOrCreateValue(op, actualParams, loc).value();
797 auto *path = llvm::cast<evaluator::BasePathValue>(valueResult.get());
798 auto result = evaluateValue(op.getBasePath(), actualParams, loc);
801 auto &value = result.value();
802 if (!value->isFullyEvaluated())
806 if (result.value()->isUnknown()) {
807 valueResult->markUnknown();
811 path->setBasepath(*llvm::cast<evaluator::BasePathValue>(value.get()));
815FailureOr<evaluator::EvaluatorValuePtr>
820 auto valueResult = getOrCreateValue(op, actualParams, loc).value();
821 auto *path = llvm::cast<evaluator::PathValue>(valueResult.get());
822 auto result = evaluateValue(op.getBasePath(), actualParams, loc);
825 auto &value = result.value();
826 if (!value->isFullyEvaluated())
830 if (result.value()->isUnknown()) {
831 valueResult->markUnknown();
835 path->setBasepath(*llvm::cast<evaluator::BasePathValue>(value.get()));
841 auto valueResult = getOrCreateValue(op, actualParams, loc).value();
846FailureOr<evaluator::EvaluatorValuePtr>
852 TypeSwitch<Type, FailureOr<EvaluatorValuePtr>>(type)
853 .Case([&](ListType type) -> FailureOr<EvaluatorValuePtr> {
855 return success(std::make_shared<ListValue>(type, loc));
857 .Case([&](ClassType type) -> FailureOr<EvaluatorValuePtr> {
860 symbolTable.lookup<ClassLike>(type.getClassName().getValue());
862 return symbolTable.getOp()->emitError(
"unknown class name ")
863 << type.getClassName();
866 return success(std::make_shared<ObjectValue>(classDef, loc));
868 .Case([&](FrozenBasePathType type) -> FailureOr<EvaluatorValuePtr> {
870 return success(std::make_shared<BasePathValue>(type.getContext()));
872 .Case([&](FrozenPathType type) -> FailureOr<EvaluatorValuePtr> {
875 std::make_shared<PathValue>(PathValue::getEmptyPath(loc)));
877 .Default([&](Type type) -> FailureOr<EvaluatorValuePtr> {
880 return success(AttributeValue::get(type, LocationAttr(loc)));
884 if (succeeded(result))
885 result->get()->markUnknown();
891FailureOr<evaluator::EvaluatorValuePtr>
893 return createUnknownValue(op.getType(), loc);
901FailureOr<EvaluatorValuePtr>
903 auto field = fields.find(name);
904 if (field == fields.end())
905 return cls.emitError(
"field ") << name <<
" does not exist";
906 return success(fields[name]);
912 SmallVector<Attribute> fieldNames;
913 for (
auto &f : fields)
914 fieldNames.push_back(f.first);
916 llvm::sort(fieldNames, [](Attribute a, Attribute b) {
917 return cast<StringAttr>(a).getValue() < cast<StringAttr>(b).getValue();
920 return ArrayAttr::get(cls.getContext(), fieldNames);
929 path(PathAttr::get(
context, {})) {
930 markFullyEvaluated();
934 :
EvaluatorValue(path.getContext(), Kind::BasePath, loc), path(path) {}
937 assert(isFullyEvaluated());
942 assert(!isFullyEvaluated());
943 auto newPath = llvm::to_vector(basepath.
path.getPath());
944 auto oldPath = path.getPath();
945 newPath.append(oldPath.begin(), oldPath.end());
946 path = PathAttr::get(path.getContext(), newPath);
947 markFullyEvaluated();
955 StringAttr module, StringAttr ref,
956 StringAttr field, Location loc)
958 path(path), module(module), ref(ref), field(field) {}
961 PathValue path(
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, loc);
969 return StringAttr::get(getContext(),
"OMDeleted:");
970 SmallString<64> result;
971 switch (targetKind.getValue()) {
972 case TargetKind::DontTouch:
973 result +=
"OMDontTouchedReferenceTarget";
975 case TargetKind::Instance:
976 result +=
"OMInstanceTarget";
978 case TargetKind::MemberInstance:
979 result +=
"OMMemberInstanceTarget";
981 case TargetKind::MemberReference:
982 result +=
"OMMemberReferenceTarget";
984 case TargetKind::Reference:
985 result +=
"OMReferenceTarget";
989 if (!path.getPath().empty())
990 result += path.getPath().front().module;
992 result +=
module.getValue();
994 for (
const auto &elt : path) {
995 result += elt.module.getValue();
997 result += elt.instance.getValue();
1000 if (!module.getValue().empty())
1001 result += module.getValue();
1002 if (!ref.getValue().empty()) {
1004 result += ref.getValue();
1006 if (!field.getValue().empty())
1007 result += field.getValue();
1008 return StringAttr::get(field.getContext(), result);
1012 assert(!isFullyEvaluated());
1013 auto newPath = llvm::to_vector(basepath.
getPath().getPath());
1014 auto oldPath = path.getPath();
1015 newPath.append(oldPath.begin(), oldPath.end());
1016 path = PathAttr::get(path.getContext(), newPath);
1017 markFullyEvaluated();
1025 if (cast<TypedAttr>(attr).getType() != this->type)
1026 return mlir::emitError(
getLoc(),
"cannot set AttributeValue of type ")
1027 << this->type <<
" to Attribute " << attr;
1028 if (isFullyEvaluated())
1029 return mlir::emitError(
1031 "cannot set AttributeValue that has already been fully evaluated");
1033 markFullyEvaluated();
1037std::shared_ptr<evaluator::EvaluatorValue>
1039 auto type = cast<TypedAttr>(attr).getType();
1040 auto *
context = type.getContext();
1042 loc = UnknownLoc::get(
context);
1046 if (
auto listType = dyn_cast<circt::om::ListType>(type)) {
1047 SmallVector<EvaluatorValuePtr> elements;
1048 auto listAttr = cast<om::ListAttr>(attr);
1050 listAttr.getContext(), listAttr.getElements().getValue());
1051 elements.append(values.begin(), values.end());
1052 auto list = std::make_shared<evaluator::ListValue>(listType, elements, loc);
1056 return std::shared_ptr<AttributeValue>(
1060std::shared_ptr<evaluator::EvaluatorValue>
1062 auto *
context = type.getContext();
1064 loc = UnknownLoc::get(
context);
1068 if (
auto listType = dyn_cast<circt::om::ListType>(type))
1069 return std::make_shared<evaluator::ListValue>(listType, loc);
1071 return std::shared_ptr<AttributeValue>(
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static Location getLoc(DefSlot slot)
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)
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.
mlir::ModuleOp getModule()
Get the Module this Evaluator is built from.
ArrayRef< EvaluatorValuePtr > ActualParameters
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.
FailureOr< evaluator::EvaluatorValuePtr > evaluateUnknownValue(UnknownValueOp op, Location loc)
Evaluate an unknown value.
Evaluator(ModuleOp mod)
Construct an Evaluator with an IR module.
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.
LogicalResult setAttr(Attribute attr)
friend std::shared_ptr< EvaluatorValue > get(Attribute attr, LocationAttr loc)
Attribute getAttr() const
BasePathValue(MLIRContext *context)
void setBasepath(const BasePathValue &basepath)
Set the basepath which this path is relative to.
om::PathAttr getPath() const
Base class for evaluator runtime values.
bool isFullyEvaluated() const
void markFullyEvaluated()
A List which contains variadic length of elements with the same type.
const auto & getElements() const
om::ListType getListType() const
Return the type of the value, which is a ListType.
A composite Object, which has a type and fields.
FailureOr< EvaluatorValuePtr > getField(StringAttr field)
Get a field of the Object by name.
ArrayAttr getFieldNames()
Get all the field names of the Object.
om::ClassLike getClassOp() const
StringAttr getAsString() const
void setBasepath(const BasePathValue &basepath)
PathValue(om::TargetKindAttr targetKind, om::PathAttr path, StringAttr module, StringAttr ref, StringAttr field, Location loc)
Create a path value representing a regular path.
static PathValue getEmptyPath(Location loc)
std::shared_ptr< EvaluatorValue > EvaluatorValuePtr
A value of an object in memory.
evaluator::EvaluatorValuePtr EvaluatorValuePtr
SmallVector< EvaluatorValuePtr > getEvaluatorValuesFromAttributes(MLIRContext *context, ArrayRef< Attribute > attributes)
RAII helper to increment/decrement debugNesting.