[OM] Deprecate the OM Map and Tuple (#8606)

Remove the support for OM Map and Tuple. 
All the dependence on them have been removed.
---------

Co-authored-by: Mike Urbach <mikeurbach@gmail.com>
This commit is contained in:
Prithayan Barua 2025-07-14 19:57:59 -07:00 committed by GitHub
parent e5603e1437
commit 2beb8e783f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 13 additions and 975 deletions

View File

@ -61,12 +61,6 @@ MLIR_CAPI_EXPORTED MlirTypeID omListTypeGetTypeID(void);
// Return a element type of a ListType.
MLIR_CAPI_EXPORTED MlirType omListTypeGetElementType(MlirType type);
/// Is the Type a MapType.
MLIR_CAPI_EXPORTED bool omTypeIsAMapType(MlirType type);
// Return a key type of a MapType.
MLIR_CAPI_EXPORTED MlirType omMapTypeGetKeyType(MlirType type);
/// Is the Type a StringType.
MLIR_CAPI_EXPORTED bool omTypeIsAStringType(MlirType type);
@ -187,31 +181,6 @@ omEvaluatorListGetNumElements(OMEvaluatorValue evaluatorValue);
MLIR_CAPI_EXPORTED OMEvaluatorValue
omEvaluatorListGetElement(OMEvaluatorValue evaluatorValue, intptr_t pos);
/// Query if the EvaluatorValue is a Tuple.
MLIR_CAPI_EXPORTED bool
omEvaluatorValueIsATuple(OMEvaluatorValue evaluatorValue);
/// Get the size of the tuple.
MLIR_CAPI_EXPORTED intptr_t
omEvaluatorTupleGetNumElements(OMEvaluatorValue evaluatorValue);
/// Get an element of the tuple.
MLIR_CAPI_EXPORTED OMEvaluatorValue
omEvaluatorTupleGetElement(OMEvaluatorValue evaluatorValue, intptr_t pos);
/// Get an element of the map.
MLIR_CAPI_EXPORTED OMEvaluatorValue
omEvaluatorMapGetElement(OMEvaluatorValue evaluatorValue, MlirAttribute attr);
MLIR_CAPI_EXPORTED MlirAttribute omEvaluatorMapGetKeys(OMEvaluatorValue object);
/// Query if the EvaluatorValue is a Map.
MLIR_CAPI_EXPORTED bool omEvaluatorValueIsAMap(OMEvaluatorValue evaluatorValue);
/// Get the Type from a Map, which will be a MapType.
MLIR_CAPI_EXPORTED MlirType
omEvaluatorMapGetType(OMEvaluatorValue evaluatorValue);
/// Query if the EvaluatorValue is a BasePath.
MLIR_CAPI_EXPORTED bool
omEvaluatorValueIsABasePath(OMEvaluatorValue evaluatorValue);
@ -275,20 +244,6 @@ MLIR_CAPI_EXPORTED MlirAttribute omListAttrGet(MlirType elementType,
intptr_t numElements,
const MlirAttribute *elements);
//===----------------------------------------------------------------------===//
// MapAttr API
//===----------------------------------------------------------------------===//
MLIR_CAPI_EXPORTED bool omAttrIsAMapAttr(MlirAttribute attr);
MLIR_CAPI_EXPORTED intptr_t omMapAttrGetNumElements(MlirAttribute attr);
MLIR_CAPI_EXPORTED MlirIdentifier omMapAttrGetElementKey(MlirAttribute attr,
intptr_t pos);
MLIR_CAPI_EXPORTED MlirAttribute omMapAttrGetElementValue(MlirAttribute attr,
intptr_t pos);
#ifdef __cplusplus
}
#endif

View File

@ -47,7 +47,7 @@ using ObjectFields = SmallDenseMap<StringAttr, EvaluatorValuePtr>;
/// the appropriate reference count.
struct EvaluatorValue : std::enable_shared_from_this<EvaluatorValue> {
// Implement LLVM RTTI.
enum class Kind { Attr, Object, List, Tuple, Map, Reference, BasePath, Path };
enum class Kind { Attr, Object, List, Reference, BasePath, Path };
EvaluatorValue(MLIRContext *ctx, Kind kind, Location loc)
: kind(kind), ctx(ctx), loc(loc) {}
Kind getKind() const { return kind; }
@ -224,44 +224,6 @@ private:
SmallVector<EvaluatorValuePtr> elements;
};
/// A Map value.
struct MapValue : EvaluatorValue {
MapValue(om::MapType type, DenseMap<Attribute, EvaluatorValuePtr> elements,
Location loc)
: EvaluatorValue(type.getContext(), Kind::Map, loc), type(type),
elements(std::move(elements)) {
markFullyEvaluated();
}
// Partially evaluated value.
MapValue(om::MapType type, Location loc)
: EvaluatorValue(type.getContext(), Kind::Map, loc), type(type) {}
const auto &getElements() const { return elements; }
void setElements(DenseMap<Attribute, EvaluatorValuePtr> newElements) {
elements = std::move(newElements);
markFullyEvaluated();
}
// Finalize the evaluator value.
LogicalResult finalizeImpl();
/// Return the type of the value, which is a MapType.
om::MapType getMapType() const { return type; }
/// Return an array of keys in the ascending order.
ArrayAttr getKeys();
/// Implement LLVM RTTI.
static bool classof(const EvaluatorValue *e) {
return e->getKind() == Kind::Map;
}
private:
om::MapType type;
DenseMap<Attribute, EvaluatorValuePtr> elements;
};
/// A composite Object, which has a type and fields.
struct ObjectValue : EvaluatorValue {
ObjectValue(om::ClassOp cls, ObjectFields fields, Location loc)
@ -313,46 +275,6 @@ private:
llvm::SmallDenseMap<StringAttr, EvaluatorValuePtr> fields;
};
/// Tuple values.
struct TupleValue : EvaluatorValue {
using TupleElements = llvm::SmallVector<EvaluatorValuePtr>;
TupleValue(TupleType type, TupleElements tupleElements, Location loc)
: EvaluatorValue(type.getContext(), Kind::Tuple, loc), type(type),
elements(std::move(tupleElements)) {
markFullyEvaluated();
}
// Partially evaluated value.
TupleValue(TupleType type, Location loc)
: EvaluatorValue(type.getContext(), Kind::Tuple, loc), type(type) {}
void setElements(TupleElements newElements) {
elements = std::move(newElements);
markFullyEvaluated();
}
LogicalResult finalizeImpl() {
for (auto &&value : elements)
if (failed(finalizeEvaluatorValue(value)))
return failure();
return success();
}
/// Implement LLVM RTTI.
static bool classof(const EvaluatorValue *e) {
return e->getKind() == Kind::Tuple;
}
/// Return the type of the value, which is a TupleType.
TupleType getTupleType() const { return type; }
const TupleElements &getElements() const { return elements; }
private:
TupleType type;
TupleElements elements;
};
/// A Basepath value.
struct BasePathValue : EvaluatorValue {
BasePathValue(MLIRContext *context);
@ -493,14 +415,6 @@ private:
FailureOr<EvaluatorValuePtr> evaluateListConcat(ListConcatOp op,
ActualParameters actualParams,
Location loc);
FailureOr<EvaluatorValuePtr>
evaluateTupleCreate(TupleCreateOp op, ActualParameters actualParams,
Location loc);
FailureOr<EvaluatorValuePtr>
evaluateTupleGet(TupleGetOp op, ActualParameters actualParams, Location loc);
FailureOr<evaluator::EvaluatorValuePtr>
evaluateMapCreate(MapCreateOp op, ActualParameters actualParams,
Location loc);
FailureOr<evaluator::EvaluatorValuePtr>
evaluateBasePathCreate(FrozenBasePathCreateOp op,
ActualParameters actualParams, Location loc);
@ -543,8 +457,6 @@ operator<<(mlir::Diagnostic &diag,
diag << "Object(" << object->getType() << ")";
else if (auto *list = llvm::dyn_cast<evaluator::ListValue>(&evaluatorValue))
diag << "List(" << list->getType() << ")";
else if (auto *map = llvm::dyn_cast<evaluator::MapValue>(&evaluatorValue))
diag << "Map(" << map->getType() << ")";
else if (llvm::isa<evaluator::BasePathValue>(&evaluatorValue))
diag << "BasePath()";
else if (llvm::isa<evaluator::PathValue>(&evaluatorValue))

View File

@ -81,28 +81,6 @@ def OMListAttr : AttrDef<OMDialect, "List", [TypedAttrInterface]> {
}];
}
def MapAttr : AttrDef<OMDialect, "Map", [TypedAttrInterface]> {
let summary = "An attribute that represents a string map";
let mnemonic = "map";
let parameters = (ins
"mlir::Type": $valueType,
"mlir::DictionaryAttr":$elements
);
// TODO: Use custom assembly format to infer a type from elements.
let assemblyFormat = [{
`<` $valueType `,` $elements `>`
}];
let genVerifyDecl = 1;
let extraClassDeclaration = [{
mlir::Type getType();
}];
}
def OMPathAttr : AttrDef<OMDialect, "Path"> {
let summary = "An attribute that represents an instance path";

View File

@ -280,94 +280,6 @@ def ListConcatOp : OMOp<"list_concat", [Pure, SameOperandsAndResultType]> {
let assemblyFormat = "$subLists attr-dict `:` type($result)";
}
def TupleCreateOp : OMOp<"tuple_create", [Pure, InferTypeOpInterface]> {
let summary = "Create a tuple of values";
let description = [{
Create a tuple from a sequence of inputs.
```
%tuple = om.tuple_create %a, %b, %c : !om.ref, !om.string, !om.list<i32>
```
}];
let arguments = (ins Variadic<AnyType>:$inputs);
let results = (outs
TupleOf<[AnyType]>:$result
);
let assemblyFormat = [{
$inputs attr-dict `:` type($inputs)
}];
let extraClassDeclaration = [{
// Implement InferTypeOpInterface.
static ::mlir::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
::mlir::OpaqueProperties,
::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes);
}];
}
def TupleGetOp : OMOp<"tuple_get", [Pure, InferTypeOpInterface]> {
let summary = "Extract a value from a tuple";
let description = [{
Extract a value from a tuple.
```
%value = om.tuple_get %a[0] : tuple<!om.ref, !om.string, !om.list<i32>>
```
}];
let arguments = (ins
TupleOf<[AnyType]>:$input,
I32Attr:$index
);
let results = (outs
AnyType:$result
);
let assemblyFormat = [{
$input `[` $index `]` attr-dict `:` type($input)
}];
let extraClassDeclaration = [{
// Implement InferTypeOpInterface.
static ::mlir::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
::mlir::OpaqueProperties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes);
}];
}
def MapKeyValuePair: Type<CPred<"::circt::om::isMapKeyValuePairType($_self)">,
"a pair whose first element is an attribute",
"::mlir::TupleType">;
def MapCreateOp : OMOp<"map_create", [Pure, SameTypeOperands]> {
let summary = "Create a map";
let description = [{
Creates a map from a sequence of inputs.
```
%map = om.map_create %e1, %e2 : !om.string, i8
```
where `%e1` and `e2` have !om.tuple<!om.string, i8> and
`%map` has `!om.map<!om.string, i8>` type.
}];
let arguments = (ins Variadic<MapKeyValuePair>:$inputs);
let results = (outs
MapType:$result
);
let hasCustomAssemblyFormat = true;
}
def BasePathCreateOp : OMOp<"basepath_create", [Pure,
DeclareOpInterfaceMethods<SymbolUserOpInterface>
]> {

View File

@ -16,12 +16,7 @@
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"
namespace circt::om {
// Return true if the type is a pair whose first element is either string or
// integer.
bool isMapKeyValuePairType(mlir::Type);
} // namespace circt::om
namespace circt::om {} // namespace circt::om
#define GET_TYPEDEF_CLASSES
#include "circt/Dialect/OM/OMTypes.h.inc"

View File

@ -51,25 +51,6 @@ def ListType : TypeDef<OMDialect, "List", []> {
];
}
def MapType : TypeDef<OMDialect, "Map", []> {
let summary = [{A type that represents a map. A key type must be either
an integer or string type}];
let mnemonic = "map";
let parameters = (ins "mlir::Type": $keyType, "mlir::Type":$valueType);
let assemblyFormat = [{
`<` $keyType `,` $valueType `>`
}];
let builders = [
AttrBuilderWithInferredContext<(ins "::mlir::Type":$keyType, "::mlir::Type":$valueType), [{
return $_get(keyType.getContext(), keyType, valueType);
}]>
];
let genVerifyDecl = 1;
}
def SymbolRefType : TypeDef<OMDialect, "SymbolRef", []> {
let summary = "A type that represents a reference to a flat symbol reference.";

View File

@ -33,7 +33,7 @@ with Context() as ctx, Location.unknown():
om.class.fields %2, %0, %0 : !om.class.type<@comp>, !om.class.type<@node>, !om.class.type<@node>
}
om.class @Test(%param: !om.integer) -> (field: !om.integer, child: !om.class.type<@Child>, reference: !om.ref, list: !om.list<!om.string>, tuple: tuple<!om.list<!om.string>, !om.integer>, nest: !om.class.type<@Nest>, map: !om.map<!om.string, !om.integer>, map_create: !om.map<!om.string, !om.integer>, true: i1, false: i1) {
om.class @Test(%param: !om.integer) -> (field: !om.integer, child: !om.class.type<@Child>, reference: !om.ref, list: !om.list<!om.string>, nest: !om.class.type<@Nest>, true: i1, false: i1) {
%sym = om.constant #om.ref<<@Root::@x>> : !om.ref
%c_14 = om.constant #om.integer<14> : !om.integer
@ -42,26 +42,18 @@ with Context() as ctx, Location.unknown():
%list = om.constant #om.list<!om.string, ["X" : !om.string, "Y" : !om.string]> : !om.list<!om.string>
%tuple = om.tuple_create %list, %c_14: !om.list<!om.string>, !om.integer
%c_15 = om.constant #om.integer<15> : !om.integer
%1 = om.object @Child(%c_15) : (!om.integer) -> !om.class.type<@Child>
%list_child = om.list_create %0, %1: !om.class.type<@Child>
%2 = om.object @Nest(%list_child) : (!om.list<!om.class.type<@Child>>) -> !om.class.type<@Nest>
%3 = om.constant #om.map<!om.integer, {a = #om.integer<42>, b = #om.integer<32>}> : !om.map<!om.string, !om.integer>
%x = om.constant "X" : !om.string
%y = om.constant "Y" : !om.string
%entry1 = om.tuple_create %x, %c_14: !om.string, !om.integer
%entry2 = om.tuple_create %y, %c_15: !om.string, !om.integer
%map = om.map_create %entry1, %entry2: !om.string, !om.integer
%true = om.constant true
%false = om.constant false
om.class.fields %param, %0, %sym, %list, %tuple, %2, %3, %map, %true, %false : !om.integer, !om.class.type<@Child>, !om.ref, !om.list<!om.string>, tuple<!om.list<!om.string>, !om.integer>, !om.class.type<@Nest>, !om.map<!om.string, !om.integer>, !om.map<!om.string, !om.integer>, i1, i1
om.class.fields %param, %0, %sym, %list, %2, %true, %false : !om.integer, !om.class.type<@Child>, !om.ref, !om.list<!om.string>, !om.class.type<@Nest>, i1, i1
}
om.class @Child(%0: !om.integer) -> (foo: !om.integer) {
@ -158,21 +150,6 @@ print("child.foo: ", obj.child.foo)
print("child.foo.loc", obj.child.get_field_loc("foo"))
# CHECK: ('Root', 'x')
print(obj.reference)
(fst, snd) = obj.tuple
# CHECK: 14
print(snd)
# CHECK: loc("-":{{.*}}:{{.*}})
print("tuple", obj.get_field_loc("tuple"))
# CHECK: loc("-":{{.*}}:{{.*}})
print(obj.loc)
try:
print(obj.tuple[3])
except IndexError as e:
# CHECK: tuple index out of range
print(e)
for (name, field) in obj:
# location from om.class.field @child, %0 : !om.class.type<@Child>
@ -196,38 +173,6 @@ for child in obj.nest.list_child:
# CHECK-NEXT: 15
print(child.foo)
# CHECK: 2
print(len(obj.map))
# CHECK: {'a': 42, 'b': 32}
print(obj.map)
for k, v in obj.map.items():
# CHECK-NEXT: a 42
# CHECK-NEXT: b 32
print(k, v)
try:
print(obj.map_create[1])
except KeyError as e:
# CHECK-NEXT: 'key is not integer'
print(e)
try:
print(obj.map_create["INVALID"])
except KeyError as e:
# CHECK-NEXT: 'key not found'
print(e)
# CHECK-NEXT: 14
print(obj.map_create["X"])
for k, v in obj.map_create.items():
# CHECK-NEXT: X 14
# CHECK-NEXT: Y 15
print(k, v)
# CHECK: True
print(obj.true)
# CHECK: False
print(obj.false)
obj = evaluator.instantiate("Client")
object_dict: Dict[om.Object, str] = {}
for field_name, data in obj:

View File

@ -26,8 +26,6 @@ namespace {
struct List;
struct Object;
struct Tuple;
struct Map;
struct BasePath;
struct Path;
@ -42,8 +40,8 @@ using PythonPrimitive = std::variant<nb::int_, nb::float_, nb::str, nb::bool_,
/// MlirAttribute and the upstream MLIR type casters. If the MlirAttribute
/// is tried first, then we can hit an assert inside the MLIR codebase.
struct None {};
using PythonValue = std::variant<None, Object, List, Tuple, Map, BasePath, Path,
PythonPrimitive>;
using PythonValue =
std::variant<None, Object, List, BasePath, Path, PythonPrimitive>;
/// Map an opaque OMEvaluatorValue into a python value.
PythonValue omEvaluatorValueToPythonValue(OMEvaluatorValue result);
@ -69,58 +67,6 @@ private:
OMEvaluatorValue value;
};
struct Tuple {
// Instantiate a Tuple with a reference to the underlying OMEvaluatorValue.
Tuple(OMEvaluatorValue value) : value(value) {}
/// Return the number of elements.
intptr_t getNumElements() { return omEvaluatorTupleGetNumElements(value); }
PythonValue getElement(intptr_t i);
OMEvaluatorValue getValue() const { return value; }
private:
// The underlying CAPI value.
OMEvaluatorValue value;
};
/// Provides a Map class by simply wrapping the OMObject CAPI.
struct Map {
// Instantiate a Map with a reference to the underlying OMEvaluatorValue.
Map(OMEvaluatorValue value) : value(value) {}
/// Return the keys.
std::vector<nb::str> getKeys() {
auto attr = omEvaluatorMapGetKeys(value);
intptr_t numFieldNames = mlirArrayAttrGetNumElements(attr);
std::vector<nb::str> pyFieldNames;
for (intptr_t i = 0; i < numFieldNames; ++i) {
auto name = mlirStringAttrGetValue(mlirArrayAttrGetElement(attr, i));
pyFieldNames.emplace_back(nb::str(name.data, name.length));
}
return pyFieldNames;
}
/// Look up the value. A key is an integer, string or attribute.
PythonValue dunderGetItemAttr(MlirAttribute key);
PythonValue dunderGetItemNamed(const std::string &key);
PythonValue dunderGetItemIndexed(intptr_t key);
PythonValue
dunderGetItem(std::variant<intptr_t, std::string, MlirAttribute> key);
/// Return a context from an underlying value.
MlirContext getContext() const { return omEvaluatorValueGetContext(value); }
OMEvaluatorValue getValue() const { return value; }
MlirType getType() { return omEvaluatorMapGetType(value); }
private:
// The underlying CAPI value.
OMEvaluatorValue value;
};
/// Provides a BasePath class by simply wrapping the OMObject CAPI.
struct BasePath {
/// Instantiate a BasePath with a reference to the underlying
@ -289,80 +235,6 @@ private:
PythonValue List::getElement(intptr_t i) {
return omEvaluatorValueToPythonValue(omEvaluatorListGetElement(value, i));
}
class PyMapAttrIterator {
public:
PyMapAttrIterator(MlirAttribute attr) : attr(std::move(attr)) {}
PyMapAttrIterator &dunderIter() { return *this; }
nb::tuple dunderNext() {
if (nextIndex >= omMapAttrGetNumElements(attr))
throw nb::stop_iteration();
MlirIdentifier key = omMapAttrGetElementKey(attr, nextIndex);
PythonValue value =
omPrimitiveToPythonValue(omMapAttrGetElementValue(attr, nextIndex));
nextIndex++;
auto keyName = mlirIdentifierStr(key);
std::string keyStr(keyName.data, keyName.length);
return nb::make_tuple(keyStr, value);
}
static void bind(nb::module_ &m) {
nb::class_<PyMapAttrIterator>(m, "MapAttributeIterator")
.def("__iter__", &PyMapAttrIterator::dunderIter)
.def("__next__", &PyMapAttrIterator::dunderNext);
}
private:
MlirAttribute attr;
intptr_t nextIndex = 0;
};
PythonValue Tuple::getElement(intptr_t i) {
if (i < 0 || i >= omEvaluatorTupleGetNumElements(value))
throw std::out_of_range("tuple index out of range");
return omEvaluatorValueToPythonValue(omEvaluatorTupleGetElement(value, i));
}
PythonValue Map::dunderGetItemNamed(const std::string &key) {
MlirType type = omMapTypeGetKeyType(omEvaluatorMapGetType(value));
if (!omTypeIsAStringType(type))
throw nanobind::key_error("key is not string");
MlirAttribute attr =
mlirStringAttrTypedGet(type, mlirStringRefCreateFromCString(key.c_str()));
return dunderGetItemAttr(attr);
}
PythonValue Map::dunderGetItemIndexed(intptr_t i) {
MlirType type = omMapTypeGetKeyType(omEvaluatorMapGetType(value));
if (!mlirTypeIsAInteger(type))
throw nanobind::key_error("key is not integer");
MlirAttribute attr = mlirIntegerAttrGet(type, i);
return dunderGetItemAttr(attr);
}
PythonValue Map::dunderGetItemAttr(MlirAttribute key) {
OMEvaluatorValue result = omEvaluatorMapGetElement(value, key);
if (omEvaluatorValueIsNull(result))
throw nanobind::key_error("key not found");
return omEvaluatorValueToPythonValue(result);
}
PythonValue
Map::dunderGetItem(std::variant<intptr_t, std::string, MlirAttribute> key) {
if (auto *i = std::get_if<intptr_t>(&key))
return dunderGetItemIndexed(*i);
else if (auto *str = std::get_if<std::string>(&key))
return dunderGetItemNamed(*str);
return dunderGetItemAttr(std::get<MlirAttribute>(key));
}
// Convert a generic MLIR Attribute to a PythonValue. This is basically a C++
// fast path of the parts of attribute_to_var that we use in the OM dialect.
static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) {
@ -411,17 +283,6 @@ static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) {
return results;
}
if (omAttrIsAMapAttr(attr)) {
nb::dict results;
for (intptr_t i = 0, e = omMapAttrGetNumElements(attr); i < e; ++i) {
auto keyStrRef = mlirIdentifierStr(omMapAttrGetElementKey(attr, i));
auto key = nb::str(keyStrRef.data, keyStrRef.length);
auto value = omPrimitiveToPythonValue(omMapAttrGetElementValue(attr, i));
results[key] = value;
}
return results;
}
mlirAttributeDump(attr);
throw nb::type_error("Unexpected OM primitive attribute");
}
@ -493,14 +354,6 @@ PythonValue omEvaluatorValueToPythonValue(OMEvaluatorValue result) {
if (omEvaluatorValueIsAList(result))
return List(result);
// If the field was a tuple, return a new Tuple.
if (omEvaluatorValueIsATuple(result))
return Tuple(result);
// If the field was a map, return a new Map.
if (omEvaluatorValueIsAMap(result))
return Map(result);
// If the field was a base path, return a new BasePath.
if (omEvaluatorValueIsABasePath(result))
return BasePath(result);
@ -523,12 +376,6 @@ OMEvaluatorValue pythonValueToOMEvaluatorValue(PythonValue result,
if (auto *list = std::get_if<List>(&result))
return list->getValue();
if (auto *tuple = std::get_if<Tuple>(&result))
return tuple->getValue();
if (auto *map = std::get_if<Map>(&result))
return map->getValue();
if (auto *basePath = std::get_if<BasePath>(&result))
return basePath->getValue();
@ -563,18 +410,6 @@ void circt::python::populateDialectOMSubmodule(nb::module_ &m) {
.def("__getitem__", &List::getElement)
.def("__len__", &List::getNumElements);
nb::class_<Tuple>(m, "Tuple")
.def(nb::init<Tuple>(), nb::arg("tuple"))
.def("__getitem__", &Tuple::getElement)
.def("__len__", &Tuple::getNumElements);
// Add the Map class definition.
nb::class_<Map>(m, "Map")
.def(nb::init<Map>(), nb::arg("map"))
.def("__getitem__", &Map::dunderGetItem)
.def("keys", &Map::getKeys)
.def_prop_ro("type", &Map::getType, "The Type of the Map");
// Add the BasePath class definition.
nb::class_<BasePath>(m, "BasePath")
.def(nb::init<BasePath>(), nb::arg("basepath"))
@ -628,12 +463,6 @@ void circt::python::populateDialectOMSubmodule(nb::module_ &m) {
[](MlirAttribute arr) { return PyListAttrIterator(arr); });
PyListAttrIterator::bind(m);
// Add the MapAttr definition
mlir_attribute_subclass(m, "MapAttr", omAttrIsAMapAttr)
.def("__iter__", [](MlirAttribute arr) { return PyMapAttrIterator(arr); })
.def("__len__", &omMapAttrGetNumElements);
PyMapAttrIterator::bind(m);
// Add the AnyType class definition.
mlir_type_subclass(m, "AnyType", omTypeIsAAnyType, omAnyTypeGetTypeID);

View File

@ -5,7 +5,7 @@
from __future__ import annotations
from ._om_ops_gen import *
from .._mlir_libs._circt._om import AnyType, Evaluator as BaseEvaluator, Object as BaseObject, List as BaseList, Tuple as BaseTuple, Map as BaseMap, BasePath as BaseBasePath, BasePathType, Path, PathType, ClassType, ReferenceAttr, ListAttr, ListType, MapAttr, OMIntegerAttr
from .._mlir_libs._circt._om import AnyType, Evaluator as BaseEvaluator, Object as BaseObject, List as BaseList, BasePath as BaseBasePath, BasePathType, Path, PathType, ClassType, ReferenceAttr, ListAttr, ListType, OMIntegerAttr
from ..ir import Attribute, Diagnostic, DiagnosticSeverity, Module, StringAttr, IntegerAttr, IntegerType
from ..support import attribute_to_var, var_to_attribute
@ -28,12 +28,6 @@ def wrap_mlir_object(value):
if isinstance(value, BaseList):
return List(value)
if isinstance(value, BaseTuple):
return Tuple(value)
if isinstance(value, BaseMap):
return Map(value)
if isinstance(value, BaseBasePath):
return BasePath(value)
@ -56,12 +50,6 @@ def unwrap_python_object(value):
if isinstance(value, List):
return BaseList(value)
if isinstance(value, Tuple):
return BaseTuple(value)
if isinstance(value, Map):
return BaseMap(value)
if isinstance(value, BasePath):
return BaseBasePath(value)
@ -90,47 +78,6 @@ class List(BaseList):
yield self.__getitem__(i)
class Tuple(BaseTuple):
def __init__(self, obj: BaseTuple) -> None:
super().__init__(obj)
def __getitem__(self, i):
val = super().__getitem__(i)
return wrap_mlir_object(val)
# Support iterating over a Tuple by yielding its elements.
def __iter__(self):
for i in range(0, self.__len__()):
yield self.__getitem__(i)
class Map(BaseMap):
def __init__(self, obj: BaseMap) -> None:
super().__init__(obj)
def __getitem__(self, key):
val = super().__getitem__(key)
return wrap_mlir_object(val)
def keys(self):
return [wrap_mlir_object(arg) for arg in super().keys()]
def items(self):
for i in self:
yield i
def values(self):
for (_, v) in self:
yield v
# Support iterating over a Map
def __iter__(self):
for i in super().keys():
yield (wrap_mlir_object(i), self.__getitem__(i))
class BasePath(BaseBasePath):
@staticmethod

View File

@ -248,10 +248,6 @@ def attribute_to_var(attr):
return list(map(attribute_to_var, om.ListAttr(attr)))
except ValueError:
pass
try:
return {name: attribute_to_var(value) for name, value in om.MapAttr(attr)}
except ValueError:
pass
try:
return int(str(om.OMIntegerAttr(attr)))
except ValueError:

View File

@ -90,14 +90,6 @@ MlirType omStringTypeGet(MlirContext ctx) {
/// Get the TypeID for a StringType.
MlirTypeID omStringTypeGetTypeID(void) { return wrap(StringType::getTypeID()); }
/// Is the Type a MapType.
bool omTypeIsAMapType(MlirType type) { return isa<MapType>(unwrap(type)); }
/// Return a key type of a map.
MlirType omMapTypeGetKeyType(MlirType type) {
return wrap(cast<MapType>(unwrap(type)).getKeyType());
}
//===----------------------------------------------------------------------===//
// Evaluator data structures.
//===----------------------------------------------------------------------===//
@ -196,15 +188,6 @@ MlirAttribute omEvaluatorObjectGetFieldNames(OMEvaluatorValue object) {
return wrap(llvm::cast<Object>(unwrap(object).get())->getFieldNames());
}
MlirType omEvaluatorMapGetType(OMEvaluatorValue value) {
return wrap(llvm::cast<evaluator::MapValue>(unwrap(value).get())->getType());
}
/// Get an ArrayAttr with the keys in a Map.
MlirAttribute omEvaluatorMapGetKeys(OMEvaluatorValue object) {
return wrap(llvm::cast<evaluator::MapValue>(unwrap(object).get())->getKeys());
}
/// Get a field from an Object, which must contain a field of that name.
OMEvaluatorValue omEvaluatorObjectGetField(OMEvaluatorValue object,
MlirAttribute name) {
@ -296,41 +279,6 @@ OMEvaluatorValue omEvaluatorListGetElement(OMEvaluatorValue evaluatorValue,
->getElements()[pos]);
}
/// Query if the EvaluatorValue is a Tuple.
bool omEvaluatorValueIsATuple(OMEvaluatorValue evaluatorValue) {
return isa<evaluator::TupleValue>(unwrap(evaluatorValue).get());
}
/// Get the length of the Tuple.
intptr_t omEvaluatorTupleGetNumElements(OMEvaluatorValue evaluatorValue) {
return cast<evaluator::TupleValue>(unwrap(evaluatorValue).get())
->getElements()
.size();
}
/// Get an element of the Tuple.
OMEvaluatorValue omEvaluatorTupleGetElement(OMEvaluatorValue evaluatorValue,
intptr_t pos) {
return wrap(cast<evaluator::TupleValue>(unwrap(evaluatorValue).get())
->getElements()[pos]);
}
/// Get an element of the Map.
OMEvaluatorValue omEvaluatorMapGetElement(OMEvaluatorValue evaluatorValue,
MlirAttribute attr) {
const auto &elements =
cast<evaluator::MapValue>(unwrap(evaluatorValue).get())->getElements();
const auto &it = elements.find(unwrap(attr));
if (it != elements.end())
return wrap(it->second);
return OMEvaluatorValue{nullptr};
}
/// Query if the EvaluatorValue is a map.
bool omEvaluatorValueIsAMap(OMEvaluatorValue evaluatorValue) {
return isa<evaluator::MapValue>(unwrap(evaluatorValue).get());
}
bool omEvaluatorValueIsABasePath(OMEvaluatorValue evaluatorValue) {
return isa<evaluator::BasePathValue>(unwrap(evaluatorValue).get());
}
@ -440,24 +388,3 @@ MlirAttribute omListAttrGet(MlirType elementType, intptr_t numElements,
auto *ctx = type.getContext();
return wrap(ListAttr::get(ctx, type, ArrayAttr::get(ctx, attrs)));
}
//===----------------------------------------------------------------------===//
// MapAttr API.
//===----------------------------------------------------------------------===//
bool omAttrIsAMapAttr(MlirAttribute attr) { return isa<MapAttr>(unwrap(attr)); }
intptr_t omMapAttrGetNumElements(MlirAttribute attr) {
auto mapAttr = llvm::cast<MapAttr>(unwrap(attr));
return static_cast<intptr_t>(mapAttr.getElements().size());
}
MlirIdentifier omMapAttrGetElementKey(MlirAttribute attr, intptr_t pos) {
auto mapAttr = llvm::cast<MapAttr>(unwrap(attr));
return wrap(mapAttr.getElements().getValue()[pos].getName());
}
MlirAttribute omMapAttrGetElementValue(MlirAttribute attr, intptr_t pos) {
auto mapAttr = llvm::cast<MapAttr>(unwrap(attr));
return wrap(mapAttr.getElements().getValue()[pos].getValue());
}

View File

@ -49,9 +49,8 @@ LogicalResult circt::om::evaluator::EvaluatorValue::finalize() {
finalized = true;
assert(isFullyEvaluated());
return llvm::TypeSwitch<EvaluatorValue *, LogicalResult>(this)
.Case<AttributeValue, ObjectValue, ListValue, MapValue, ReferenceValue,
TupleValue, BasePathValue, PathValue>(
[](auto v) { return v->finalizeImpl(); });
.Case<AttributeValue, ObjectValue, ListValue, ReferenceValue,
BasePathValue, PathValue>([](auto v) { return v->finalizeImpl(); });
}
Type circt::om::evaluator::EvaluatorValue::getType() const {
@ -59,9 +58,7 @@ Type circt::om::evaluator::EvaluatorValue::getType() const {
.Case<AttributeValue>([](auto *attr) -> Type { return attr->getType(); })
.Case<ObjectValue>([](auto *object) { return object->getObjectType(); })
.Case<ListValue>([](auto *list) { return list->getListType(); })
.Case<MapValue>([](auto *map) { return map->getMapType(); })
.Case<ReferenceValue>([](auto *ref) { return ref->getValueType(); })
.Case<TupleValue>([](auto *tuple) { return tuple->getTupleType(); })
.Case<BasePathValue>(
[this](auto *tuple) { return FrozenBasePathType::get(ctx); })
.Case<PathValue>(
@ -73,22 +70,11 @@ circt::om::Evaluator::getPartiallyEvaluatedValue(Type type, Location loc) {
using namespace circt::om::evaluator;
return TypeSwitch<mlir::Type, FailureOr<evaluator::EvaluatorValuePtr>>(type)
.Case([&](circt::om::MapType type) {
evaluator::EvaluatorValuePtr result =
std::make_shared<evaluator::MapValue>(type, loc);
return success(result);
})
.Case([&](circt::om::ListType type) {
evaluator::EvaluatorValuePtr result =
std::make_shared<evaluator::ListValue>(type, loc);
return success(result);
})
.Case([&](mlir::TupleType type) {
evaluator::EvaluatorValuePtr result =
std::make_shared<evaluator::TupleValue>(type, loc);
return success(result);
})
.Case([&](circt::om::ClassType type)
-> FailureOr<evaluator::EvaluatorValuePtr> {
ClassOp cls =
@ -167,13 +153,9 @@ FailureOr<evaluator::EvaluatorValuePtr> circt::om::Evaluator::getOrCreateValue(
evaluator::PathValue::getEmptyPath(loc));
return success(result);
})
.Case<ListCreateOp, ListConcatOp, TupleCreateOp, MapCreateOp,
ObjectFieldOp>([&](auto op) {
.Case<ListCreateOp, ListConcatOp, ObjectFieldOp>([&](auto op) {
return getPartiallyEvaluatedValue(op.getType(), loc);
})
.Case<TupleGetOp>([&](auto op) {
return evaluateTupleGet(op, actualParams, loc);
})
.Case<ObjectOp>([&](auto op) {
return getPartiallyEvaluatedValue(op.getType(), op.getLoc());
})
@ -369,18 +351,9 @@ circt::om::Evaluator::evaluateValue(Value value, ActualParameters actualParams,
.Case([&](ListConcatOp op) {
return evaluateListConcat(op, actualParams, loc);
})
.Case([&](TupleCreateOp op) {
return evaluateTupleCreate(op, actualParams, loc);
})
.Case([&](TupleGetOp op) {
return evaluateTupleGet(op, actualParams, loc);
})
.Case([&](AnyCastOp op) {
return evaluateValue(op.getInput(), actualParams, loc);
})
.Case([&](MapCreateOp op) {
return evaluateMapCreate(op, actualParams, loc);
})
.Case([&](FrozenBasePathCreateOp op) {
return evaluateBasePathCreate(op, actualParams, loc);
})
@ -635,67 +608,6 @@ circt::om::Evaluator::evaluateListConcat(ListConcatOp op,
return list;
}
/// Evaluator dispatch function for Tuple creation.
FailureOr<evaluator::EvaluatorValuePtr>
circt::om::Evaluator::evaluateTupleCreate(TupleCreateOp op,
ActualParameters actualParams,
Location loc) {
SmallVector<evaluator::EvaluatorValuePtr> values;
for (auto operand : op.getOperands()) {
auto result = evaluateValue(operand, actualParams, loc);
if (failed(result))
return result;
values.push_back(result.value());
}
// Return the tuple.
auto val = getOrCreateValue(op, actualParams, loc);
llvm::cast<evaluator::TupleValue>(val.value().get())
->setElements(std::move(values));
return val;
}
/// Evaluator dispatch function for List creation.
FailureOr<evaluator::EvaluatorValuePtr> circt::om::Evaluator::evaluateTupleGet(
TupleGetOp op, ActualParameters actualParams, Location loc) {
auto tuple = evaluateValue(op.getInput(), actualParams, loc);
if (failed(tuple))
return tuple;
evaluator::EvaluatorValuePtr result =
cast<evaluator::TupleValue>(tuple.value().get())
->getElements()[op.getIndex()];
return result;
}
/// Evaluator dispatch function for Map creation.
FailureOr<evaluator::EvaluatorValuePtr> circt::om::Evaluator::evaluateMapCreate(
MapCreateOp op, ActualParameters actualParams, Location loc) {
// Evaluate the Object itself, in case it hasn't been evaluated yet.
DenseMap<Attribute, evaluator::EvaluatorValuePtr> elements;
auto valueResult = getOrCreateValue(op, actualParams, loc).value();
for (auto operand : op.getOperands()) {
auto result = evaluateValue(operand, actualParams, loc);
if (failed(result))
return result;
// The result is a tuple.
auto &value = result.value();
if (!value->isFullyEvaluated())
return valueResult;
const auto &element =
llvm::cast<evaluator::TupleValue>(value.get())->getElements();
assert(element.size() == 2);
auto attr =
llvm::cast<evaluator::AttributeValue>(element[0].get())->getAttr();
if (!elements.insert({attr, element[1]}).second)
return op.emitError() << "map contains duplicated keys";
}
// Return the Map.
llvm::cast<evaluator::MapValue>(valueResult.get())
->setElements(std::move(elements));
return valueResult;
}
FailureOr<evaluator::EvaluatorValuePtr>
circt::om::Evaluator::evaluateBasePathCreate(FrozenBasePathCreateOp op,
ActualParameters actualParams,
@ -771,36 +683,6 @@ LogicalResult circt::om::evaluator::ObjectValue::finalizeImpl() {
return success();
}
//===----------------------------------------------------------------------===//
// MapValue
//===----------------------------------------------------------------------===//
/// Return an array of keys in the ascending order.
ArrayAttr circt::om::evaluator::MapValue::getKeys() {
SmallVector<Attribute> attrs;
for (auto &[key, _] : elements)
attrs.push_back(key);
std::sort(attrs.begin(), attrs.end(), [](Attribute l, Attribute r) {
if (auto lInt = dyn_cast<mlir::IntegerAttr>(l))
if (auto rInt = dyn_cast<mlir::IntegerAttr>(r))
return lInt.getValue().ult(rInt.getValue());
assert(isa<StringAttr>(l) && isa<StringAttr>(r) &&
"key type should be integer or string");
return cast<StringAttr>(l).getValue() < cast<StringAttr>(r).getValue();
});
return ArrayAttr::get(type.getContext(), attrs);
}
LogicalResult circt::om::evaluator::MapValue::finalizeImpl() {
for (auto &&[e, value] : elements)
if (failed(finalizeEvaluatorValue(value)))
return failure();
return success();
}
//===----------------------------------------------------------------------===//
// ReferenceValue
//===----------------------------------------------------------------------===//

View File

@ -14,7 +14,6 @@
#include "circt/Dialect/OM/OMDialect.h"
#include "circt/Dialect/OM/OMTypes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.h"
@ -36,11 +35,6 @@ Type circt::om::ListAttr::getType() {
return ListType::get(getContext(), getElementType());
}
Type circt::om::MapAttr::getType() {
return MapType::get(getContext(), StringType::get(getContext()),
getValueType());
}
circt::om::SymbolRefAttr circt::om::SymbolRefAttr::get(mlir::Operation *op) {
return om::SymbolRefAttr::get(op->getContext(),
mlir::FlatSymbolRefAttr::get(op));
@ -73,24 +67,6 @@ circt::om::ListAttr::verify(function_ref<InFlightDiagnostic()> emitError,
}));
}
LogicalResult
circt::om::MapAttr::verify(function_ref<InFlightDiagnostic()> emitError,
mlir::Type valueType,
mlir::DictionaryAttr elements) {
for (auto attr : elements) {
auto typedAttr = llvm::dyn_cast<mlir::TypedAttr>(attr.getValue());
if (!typedAttr)
return emitError()
<< "a value of a map attribute must be a typed attr but got "
<< attr.getValue();
if (typedAttr.getType() != valueType)
return emitError() << "a value of a map attribute must have a type "
<< valueType << " but field " << attr.getName()
<< " has " << typedAttr.getType();
}
return success();
}
void PathAttr::print(AsmPrinter &odsPrinter) const {
odsPrinter << '[';
llvm::interleaveComma(getPath(), odsPrinter, [&](PathElement element) {

View File

@ -611,80 +611,6 @@ ParseResult circt::om::ListCreateOp::parse(OpAsmParser &parser,
return success();
}
//===----------------------------------------------------------------------===//
// TupleCreateOp
//===----------------------------------------------------------------------===//
LogicalResult TupleCreateOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
DictionaryAttr attributes, OpaqueProperties, RegionRange regions,
llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
::llvm::SmallVector<Type> types;
for (auto op : operands)
types.push_back(op.getType());
inferredReturnTypes.push_back(TupleType::get(context, types));
return success();
}
//===----------------------------------------------------------------------===//
// TupleGetOp
//===----------------------------------------------------------------------===//
LogicalResult TupleGetOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
Adaptor adaptor(operands, attributes, properties, regions);
auto idx = adaptor.getIndexAttr();
if (operands.empty() || !idx)
return failure();
auto tupleTypes = cast<TupleType>(adaptor.getInput().getType()).getTypes();
if (tupleTypes.size() <= idx.getValue().getLimitedValue()) {
if (location)
mlir::emitError(*location,
"tuple index out-of-bounds, must be less than ")
<< tupleTypes.size() << " but got "
<< idx.getValue().getLimitedValue();
return failure();
}
inferredReturnTypes.push_back(tupleTypes[idx.getValue().getLimitedValue()]);
return success();
}
//===----------------------------------------------------------------------===//
// MapCreateOp
//===----------------------------------------------------------------------===//
void circt::om::MapCreateOp::print(OpAsmPrinter &p) {
p << " ";
p.printOperands(getInputs());
p.printOptionalAttrDict((*this)->getAttrs());
p << " : " << cast<circt::om::MapType>(getType()).getKeyType() << ", "
<< cast<circt::om::MapType>(getType()).getValueType();
}
ParseResult circt::om::MapCreateOp::parse(OpAsmParser &parser,
OperationState &result) {
llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
Type elementType, valueType;
if (parser.parseOperandList(operands) ||
parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
parser.parseType(elementType) || parser.parseComma() ||
parser.parseType(valueType))
return failure();
result.addTypes({circt::om::MapType::get(elementType, valueType)});
auto operandType =
mlir::TupleType::get(valueType.getContext(), {elementType, valueType});
for (auto operand : operands)
if (parser.resolveOperand(operand, operandType, result.operands))
return failure();
return success();
}
//===----------------------------------------------------------------------===//
// BasePathCreateOp
//===----------------------------------------------------------------------===//

View File

@ -30,18 +30,3 @@ void circt::om::OMDialect::registerTypes() {
#include "circt/Dialect/OM/OMTypes.cpp.inc"
>();
}
mlir::LogicalResult
circt::om::MapType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> diag,
mlir::Type keyType, mlir::Type elementType) {
if (!llvm::isa<om::StringType, mlir::IntegerType>(keyType))
return diag() << "map key type must be either string or integer but got "
<< keyType;
return mlir::success();
}
bool circt::om::isMapKeyValuePairType(mlir::Type type) {
auto tuple = llvm::dyn_cast<mlir::TupleType>(type);
return tuple && tuple.getTypes().size() == 2 &&
llvm::isa<om::StringType, mlir::IntegerType>(tuple.getTypes().front());
}

View File

@ -103,14 +103,11 @@ void testEvaluator(MlirContext ctx) {
" %0 = om.object @Child() : () -> !om.class.type<@Child>"
" om.class.fields %param, %0 : !om.integer, !om.class.type<@Child>"
" }"
" om.class @Child() -> (foo: i64, bar: !om.list<i64>, baz: "
"tuple<!om.list<i64>, i64>){"
" om.class @Child() -> (foo: i64, bar: !om.list<i64>){"
" %0 = om.constant 14 : i64"
" %1 = om.constant 15 : i64"
" %2 = om.list_create %0, %1 : i64"
" %3 = om.tuple_create %2, %0 : !om.list<i64>, i64"
" om.class.fields %0, %2, %3 : i64, !om.list<i64>, "
"tuple<!om.list<i64>, i64>"
" om.class.fields %0, %2 : i64, !om.list<i64>"
" }"
"}";
@ -202,12 +199,9 @@ void testEvaluator(MlirContext ctx) {
OMEvaluatorValue bar = omEvaluatorObjectGetField(
child, mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("bar")));
OMEvaluatorValue baz = omEvaluatorObjectGetField(
child, mlirStringAttrGet(ctx, mlirStringRefCreateFromCString("baz")));
MlirAttribute fieldNamesC = omEvaluatorObjectGetFieldNames(child);
// CHECK: ["bar", "baz", "foo"]
// CHECK: ["bar", "foo"]
mlirAttributeDump(fieldNamesC);
// CHECK: child object field `foo` is primitive: 1
@ -226,14 +220,6 @@ void testEvaluator(MlirContext ctx) {
// CHECK: 15 : i64
mlirAttributeDump(
omEvaluatorValueGetPrimitive(omEvaluatorListGetElement(bar, 1)));
// CHECK: child object field `baz` is tuple: 1
fprintf(stderr, "child object field `baz` is tuple: %d\n",
omEvaluatorValueIsATuple(baz));
// CHECK: 14 : i64
mlirAttributeDump(
omEvaluatorValueGetPrimitive(omEvaluatorTupleGetElement(baz, 1)));
}
int main(void) {

View File

@ -112,29 +112,6 @@ om.class @ListCreate() {
// -----
// expected-error @+1 {{map key type must be either string or integer but got '!om.list<!om.string>'}}
om.class @Map(%map: !om.map<!om.list<!om.string>, !om.string>) {
om.class.fields
}
// -----
om.class @Tuple(%tuple: tuple<i1, !om.string>) {
// expected-error @+1 {{tuple index out-of-bounds, must be less than 2 but got 2}}
%val = om.tuple_get %tuple[2] : tuple<i1, !om.string>
om.class.fields
}
// -----
om.class @MapConstant() {
// expected-error @+1 {{a value of a map attribute must have a type 'i64' but field "b" has '!om.list<i32>'}}
%0 = om.constant #om.map<i64, {a = 42, b = #om.list<i32, []>}> : !om.map<!om.string, i64>
om.class.fields
}
// -----
om.class @Thing() {
om.class.fields
}

View File

@ -223,43 +223,6 @@ om.class @BoolConstant(%b0 : i1) -> (bool: i1, bool2: i1, bool3: i1) {
// CHECK: om.class.fields %b0, %[[const1]], %[[const2]] : i1, i1, i1
om.class.fields %b0, %1, %2 : i1, i1, i1
}
// CHECK-LABEL: @Map
// CHECK-SAME: !om.map<!om.string, !om.string>
// CHECK-SAME: -> (field: !om.map<!om.string, !om.string>)
om.class @Map(%map: !om.map<!om.string, !om.string>) -> (field: !om.map<!om.string, !om.string>) {
// CHECK: om.class.fields %map : !om.map<!om.string, !om.string>
om.class.fields %map : !om.map<!om.string, !om.string>
}
// CHECK-LABEL: @Tuple
// CHECK-SAME: -> (tuple: tuple<i1, !om.string>, val: !om.string)
om.class @Tuple(%int: i1, %str: !om.string) -> (tuple: tuple<i1, !om.string>, val: !om.string) {
// CHECK: %[[tuple:.+]] = om.tuple_create %int, %str : i1, !om.string
%tuple = om.tuple_create %int, %str : i1, !om.string
// CHECK-NEXT: %[[tuple_get:.+]] = om.tuple_get %[[tuple]][1] : tuple<i1, !om.string>
%val = om.tuple_get %tuple[1] : tuple<i1, !om.string>
// CHECK-NEXT: om.class.fields %[[tuple]], %[[tuple_get]] : tuple<i1, !om.string>, !om.string
om.class.fields %tuple, %val : tuple<i1, !om.string>, !om.string
}
// CHECK-LABEL: @MapConstant
// CHECK-SAME: -> (map_i64: !om.map<!om.string, i64>)
om.class @MapConstant() -> (map_i64: !om.map<!om.string, i64>) {
// CHECK: %[[const1:.+]] = om.constant #om.map<i64, {a = 42 : i64, b = 32 : i64}> : !om.map<!om.string, i64>
%0 = om.constant #om.map<i64, {a = 42, b = 32}> : !om.map<!om.string, i64>
// CHECK: om.class.fields %[[const1]] : !om.map<!om.string, i64>
om.class.fields %0 : !om.map<!om.string, i64>
}
// CHECK-LABEL: @MapCreate
// CHECK-SAME: -> (map_field: !om.map<!om.string, !om.class.type<@Empty>>)
om.class @MapCreate(%e1: tuple<!om.string, !om.class.type<@Empty>>, %e2: tuple<!om.string, !om.class.type<@Empty>>) -> (map_field: !om.map<!om.string, !om.class.type<@Empty>>) {
// CHECK: %[[map:.+]] = om.map_create %e1, %e2 : !om.string, !om.class.type<@Empty>
%map = om.map_create %e1, %e2 : !om.string, !om.class.type<@Empty>
// CHECK-NEXT: om.class.fields %[[map]] : !om.map<!om.string, !om.class.type<@Empty>>
om.class.fields %map : !om.map<!om.string, !om.class.type<@Empty>>
}
hw.hierpath @HierPath [@PathModule::@wire]
hw.module @PathModule() {

View File

@ -1323,40 +1323,6 @@ TEST(EvaluatorTests, ListConcatPartialCycle) {
ASSERT_EQ(2U, id2->getAs<circt::om::IntegerAttr>().getValue().getValue());
}
TEST(EvaluatorTests, TupleGet) {
StringRef mod = "om.class @Tuple() -> (val: !om.string) {"
" %int = om.constant 1 : i1"
" %str = om.constant \"foo\" : !om.string"
" %tuple = om.tuple_create %int, %str : i1, !om.string"
" %val = om.tuple_get %tuple[1] : tuple<i1, !om.string>"
" om.class.fields %val : !om.string"
"}";
DialectRegistry registry;
registry.insert<OMDialect>();
MLIRContext context(registry);
context.getOrLoadDialect<OMDialect>();
OwningOpRef<ModuleOp> owning =
parseSourceString<ModuleOp>(mod, ParserConfig(&context));
Evaluator evaluator(owning.release());
auto result = evaluator.instantiate(StringAttr::get(&context, "Tuple"), {});
ASSERT_TRUE(succeeded(result));
auto fieldValue = llvm::cast<evaluator::ObjectValue>(result.value().get())
->getField("val")
.value();
ASSERT_EQ("foo", llvm::cast<evaluator::AttributeValue>(fieldValue.get())
->getAs<StringAttr>()
.getValue()
.str());
}
TEST(EvaluatorTests, NestedReferenceValue) {
StringRef mod =
"om.class @Empty() {"