[OM] Add C API and Python bindings for EvaluatorValue::Reference. (#6785)

In some OM dialect constructs, it is possible to receive
EvaluatorValue::Reference values. In the Python bindings, where we are
converting an EvaluatorValue to a Python value, we need to dereference
the Reference, to get at the underlying EvaluatorValue that was set
during evaluation.

This adds the necessary C APIs, and updates the Python bindings to use
them. If we encounter a Reference, we dereference it and recursively
call the converter function.

A Python test was added using an example IR from the Evaluator unit
tests, which delays evaluation and introduces references.
This commit is contained in:
Mike Urbach 2024-03-05 15:49:35 -07:00 committed by GitHub
parent 23eb8c330a
commit 675716b168
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 0 deletions

View File

@ -207,6 +207,15 @@ omEvaluatorValueIsAPath(OMEvaluatorValue evaluatorValue);
MLIR_CAPI_EXPORTED MlirAttribute
omEvaluatorPathGetAsString(OMEvaluatorValue evaluatorValue);
/// Query if the EvaluatorValue is a Reference.
MLIR_CAPI_EXPORTED bool
omEvaluatorValueIsAReference(OMEvaluatorValue evaluatorValue);
/// Dereference a Reference EvaluatorValue. Emits an error and returns null if
/// the Reference cannot be dereferenced.
MLIR_CAPI_EXPORTED OMEvaluatorValue
omEvaluatorValueGetReferenceValue(OMEvaluatorValue evaluatorValue);
//===----------------------------------------------------------------------===//
// ReferenceAttr API
//===----------------------------------------------------------------------===//

View File

@ -91,6 +91,28 @@ with Context() as ctx, Location.unknown():
%3 = om.frozenpath_empty
om.class.field @deleted, %3 : !om.frozenpath
}
om.class @Class1(%input: !om.integer) {
%0 = om.constant #om.integer<1 : si3> : !om.integer
om.class.field @value, %0 : !om.integer
om.class.field @input, %input : !om.integer
}
om.class @Class2() {
%0 = om.constant #om.integer<2 : si3> : !om.integer
om.class.field @value, %0 : !om.integer
}
om.class @IntegerBinaryArithmeticObjectsDelayed() {
%0 = om.object @Class1(%5) : (!om.integer) -> !om.class.type<@Class1>
%1 = om.object.field %0, [@value] : (!om.class.type<@Class1>) -> !om.integer
%2 = om.object @Class2() : () -> !om.class.type<@Class2>
%3 = om.object.field %2, [@value] : (!om.class.type<@Class2>) -> !om.integer
%5 = om.integer.add %1, %3 : !om.integer
om.class.field @result, %5 : !om.integer
}
}
""")
@ -232,3 +254,8 @@ paths_fields = [
]
for paths_field in paths_fields:
assert isinstance(paths_field.value.type, om.PathType)
delayed = evaluator.instantiate("IntegerBinaryArithmeticObjectsDelayed")
# CHECK: 3
print(delayed.result)

View File

@ -377,6 +377,10 @@ PythonValue omEvaluatorValueToPythonValue(OMEvaluatorValue result) {
if (omEvaluatorValueIsAPath(result))
return Path(result);
if (omEvaluatorValueIsAReference(result))
return omEvaluatorValueToPythonValue(
omEvaluatorValueGetReferenceValue(result));
// If the field was a primitive, return the Attribute.
assert(omEvaluatorValueIsAPrimitive(result));
return omEvaluatorValueGetPrimitive(result);

View File

@ -325,6 +325,31 @@ MlirAttribute omEvaluatorPathGetAsString(OMEvaluatorValue evaluatorValue) {
return wrap((Attribute)path->getAsString());
}
/// Query if the EvaluatorValue is a Reference.
bool omEvaluatorValueIsAReference(OMEvaluatorValue evaluatorValue) {
return isa<evaluator::ReferenceValue>(unwrap(evaluatorValue).get());
}
/// Dereference a Reference EvaluatorValue. Emits an error and returns null if
/// the Reference cannot be dereferenced.
OMEvaluatorValue
omEvaluatorValueGetReferenceValue(OMEvaluatorValue evaluatorValue) {
// Assert the EvaluatorValue is a Reference.
assert(omEvaluatorValueIsAReference(evaluatorValue));
// Attempt to get the final EvaluatorValue from the Reference.
auto result =
llvm::cast<evaluator::ReferenceValue>(unwrap(evaluatorValue).get())
->getStrippedValue();
// If this failed, an error diagnostic has been emitted, and we return null.
if (failed(result))
return {};
// If this succeeded, wrap the EvaluatorValue and return it.
return wrap(result.value());
}
//===----------------------------------------------------------------------===//
// ReferenceAttr API.
//===----------------------------------------------------------------------===//