@@ -1339,10 +1339,10 @@ py::object PyOperation::createOpView() {
1339
1339
checkValid ();
1340
1340
MlirIdentifier ident = mlirOperationGetName (get ());
1341
1341
MlirStringRef identStr = mlirIdentifierStr (ident);
1342
- auto opViewClass = PyGlobals::get ().lookupRawOpViewClass (
1342
+ auto operationCls = PyGlobals::get ().lookupOperationClass (
1343
1343
StringRef (identStr.data , identStr.length ));
1344
- if (opViewClass )
1345
- return (*opViewClass)( getRef ().getObject ());
1344
+ if (operationCls )
1345
+ return PyOpView::constructDerived (*operationCls, * getRef ().get ());
1346
1346
return py::cast (PyOpView (getRef ().getObject ()));
1347
1347
}
1348
1348
@@ -1618,47 +1618,23 @@ PyOpView::buildGeneric(const py::object &cls, py::list resultTypeList,
1618
1618
/* regions=*/ *regions, location, maybeIp);
1619
1619
}
1620
1620
1621
+ pybind11::object PyOpView::constructDerived (const pybind11::object &cls,
1622
+ const PyOperation &operation) {
1623
+ // TODO: pybind11 2.6 supports a more direct form.
1624
+ // Upgrade many years from now.
1625
+ // auto opViewType = py::type::of<PyOpView>();
1626
+ py::handle opViewType = py::detail::get_type_handle (typeid (PyOpView), true );
1627
+ py::object instance = cls.attr (" __new__" )(cls);
1628
+ opViewType.attr (" __init__" )(instance, operation);
1629
+ return instance;
1630
+ }
1631
+
1621
1632
PyOpView::PyOpView (const py::object &operationObject)
1622
1633
// Casting through the PyOperationBase base-class and then back to the
1623
1634
// Operation lets us accept any PyOperationBase subclass.
1624
1635
: operation(py::cast<PyOperationBase &>(operationObject).getOperation()),
1625
1636
operationObject(operation.getRef().getObject()) {}
1626
1637
1627
- py::object PyOpView::createRawSubclass (const py::object &userClass) {
1628
- // This is... a little gross. The typical pattern is to have a pure python
1629
- // class that extends OpView like:
1630
- // class AddFOp(_cext.ir.OpView):
1631
- // def __init__(self, loc, lhs, rhs):
1632
- // operation = loc.context.create_operation(
1633
- // "addf", lhs, rhs, results=[lhs.type])
1634
- // super().__init__(operation)
1635
- //
1636
- // I.e. The goal of the user facing type is to provide a nice constructor
1637
- // that has complete freedom for the op under construction. This is at odds
1638
- // with our other desire to sometimes create this object by just passing an
1639
- // operation (to initialize the base class). We could do *arg and **kwargs
1640
- // munging to try to make it work, but instead, we synthesize a new class
1641
- // on the fly which extends this user class (AddFOp in this example) and
1642
- // *give it* the base class's __init__ method, thus bypassing the
1643
- // intermediate subclass's __init__ method entirely. While slightly,
1644
- // underhanded, this is safe/legal because the type hierarchy has not changed
1645
- // (we just added a new leaf) and we aren't mucking around with __new__.
1646
- // Typically, this new class will be stored on the original as "_Raw" and will
1647
- // be used for casts and other things that need a variant of the class that
1648
- // is initialized purely from an operation.
1649
- py::object parentMetaclass =
1650
- py::reinterpret_borrow<py::object>((PyObject *)&PyType_Type);
1651
- py::dict attributes;
1652
- // TODO: pybind11 2.6 supports a more direct form. Upgrade many years from
1653
- // now.
1654
- // auto opViewType = py::type::of<PyOpView>();
1655
- auto opViewType = py::detail::get_type_handle (typeid (PyOpView), true );
1656
- attributes[" __init__" ] = opViewType.attr (" __init__" );
1657
- py::str origName = userClass.attr (" __name__" );
1658
- py::str newName = py::str (" _" ) + origName;
1659
- return parentMetaclass (newName, py::make_tuple (userClass), attributes);
1660
- }
1661
-
1662
1638
// ------------------------------------------------------------------------------
1663
1639
// PyInsertionPoint.
1664
1640
// ------------------------------------------------------------------------------
@@ -2863,7 +2839,7 @@ void mlir::python::populateIRCore(py::module &m) {
2863
2839
throw py::value_error (
2864
2840
" Expected a '" + clsOpName + " ' op, got: '" +
2865
2841
std::string (parsedOpName.data , parsedOpName.length ) + " '" );
2866
- return cls. attr ( " _Raw " )( parsed.getObject ());
2842
+ return PyOpView::constructDerived (cls, * parsed.get ());
2867
2843
},
2868
2844
py::arg (" cls" ), py::arg (" source" ), py::kw_only (),
2869
2845
py::arg (" source_name" ) = " " , py::arg (" context" ) = py::none (),
0 commit comments