Skip to content

Commit

Permalink
[Python] Manually cast enums while we transition to nanobind.
Browse files Browse the repository at this point in the history
As we transition from pybind11 to nanobind, the enums defined upstream
will be defined by nanobind. This no longer works with automatic
casting in the pybind11 APIs we define ourselves. To work around this
while we smooth the transition, this updates the APIs to work with
plain py::objects and manually cast to the appropriate C API enums in
a way that's compatible with both the pybind11 and nanobind versions
of enums.
  • Loading branch information
mikeurbach committed Dec 19, 2024
1 parent 812cbe9 commit b56dacc
Showing 1 changed file with 40 additions and 4 deletions.
44 changes: 40 additions & 4 deletions lib/Bindings/Python/SupportModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,32 @@ void circt::python::populateSupportSubmodule(py::module &m) {
m.def(
"_walk_with_filter",
[](MlirOperation operation, const std::vector<std::string> &opNames,
std::function<MlirWalkResult(MlirOperation)> callback,
MlirWalkOrder walkOrder) {
std::function<py::object(MlirOperation)> callback,
py::object walkOrderRaw) {
struct UserData {
std::function<MlirWalkResult(MlirOperation)> callback;
std::function<py::object(MlirOperation)> callback;
bool gotException;
std::string exceptionWhat;
py::object exceptionType;
std::vector<MlirIdentifier> opNames;
};

// As we transition from pybind11 to nanobind, the WalkOrder enum and
// automatic casting will be defined as a nanobind enum upstream. Do a
// manual conversion that works with either pybind11 or nanobind for
// now. When we're on nanobind in CIRCT, we can go back to automatic
// casting.
MlirWalkOrder walkOrder;
auto walkOrderRawValue = py::cast<int>(walkOrderRaw.attr("value"));
switch (walkOrderRawValue) {
case 0:
walkOrder = MlirWalkOrder::MlirWalkPreOrder;
break;
case 1:
walkOrder = MlirWalkOrder::MlirWalkPostOrder;
break;
}

std::vector<MlirIdentifier> opNamesIdentifiers;
opNamesIdentifiers.reserve(opNames.size());

Expand Down Expand Up @@ -68,7 +84,27 @@ void circt::python::populateSupportSubmodule(py::module &m) {
return MlirWalkResult::MlirWalkResultAdvance;

try {
return (calleeUserData->callback)(op);
// As we transition from pybind11 to nanobind, the WalkResult enum
// and automatic casting will be defined as a nanobind enum
// upstream. Do a manual conversion that works with either pybind11
// or nanobind for now. When we're on nanobind in CIRCT, we can go
// back to automatic casting.
MlirWalkResult walkResult;
auto walkResultRaw = (calleeUserData->callback)(op);
auto walkResultRawValue =
py::cast<int>(walkResultRaw.attr("value"));
switch (walkResultRawValue) {
case 0:
walkResult = MlirWalkResult::MlirWalkResultAdvance;
break;
case 1:
walkResult = MlirWalkResult::MlirWalkResultInterrupt;
break;
case 2:
walkResult = MlirWalkResult::MlirWalkResultSkip;
break;
}
return walkResult;
} catch (py::error_already_set &e) {
calleeUserData->gotException = true;
calleeUserData->exceptionWhat = e.what();
Expand Down

0 comments on commit b56dacc

Please sign in to comment.