Files
llvm/mlir/lib/Bindings/Python/PybindUtils.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

103 lines
3.5 KiB
C
Raw Normal View History

//===- PybindUtils.h - Utilities for interop with pybind11 ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_BINDINGS_PYTHON_PYBINDUTILS_H
#define MLIR_BINDINGS_PYTHON_PYBINDUTILS_H
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Twine.h"
namespace mlir {
namespace python {
// Sets a python error, ready to be thrown to return control back to the
// python runtime.
// Correct usage:
// throw SetPyError(PyExc_ValueError, "Foobar'd");
pybind11::error_already_set SetPyError(PyObject *excClass,
const llvm::Twine &message);
[mlir][Python] Context managers for Context, InsertionPoint, Location. * Finishes support for Context, InsertionPoint and Location to be carried by the thread using context managers. * Introduces type casters and utilities so that DefaultPyMlirContext and DefaultPyLocation in method signatures does the right thing (allows explicit or gets from the thread context). * Extend the rules for the thread context stack to handle nesting, appropriately inheriting and clearing depending on whether the context is the same. * Refactors all method signatures to follow the new convention on trailing parameters for defaulting parameters (loc, ip, context). When the objects are carried in the thread context, this allows most explicit uses of these values to be elided. * Removes the style guide section on putting accessors to construct global objects on the PyMlirContext: this style fails to make good use of the new facility since it is often the only thing remaining needing an MlirContext. * Moves Module parse/creation from mlir.ir.Context to static methods on mlir.ir.Module. * Moves Context.create_operation to a static Operation.create method. * Moves Type parsing from mlir.ir.Context to static methods on mlir.ir.Type. * Moves Attribute parsing from mlir.ir.Context to static methods on mlir.ir.Attribute. * Move Location factory methods from mlir.ir.Context to static methods on mlir.ir.Location. * Refactors the std dialect fake "ODS" generated code to take advantage of the new scheme. Differential Revision: https://reviews.llvm.org/D90547
2020-10-31 23:40:25 -07:00
/// CRTP template for special wrapper types that are allowed to be passed in as
/// 'None' function arguments and can be resolved by some global mechanic if
/// so. Such types will raise an error if this global resolution fails, and
/// it is actually illegal for them to ever be unresolved. From a user
/// perspective, they behave like a smart ptr to the underlying type (i.e.
/// 'get' method and operator-> overloaded).
///
/// Derived types must provide a method, which is called when an environmental
/// resolution is required. It must raise an exception if resolution fails:
/// static ReferrentTy &resolve()
///
/// They must also provide a parameter description that will be used in
/// error messages about mismatched types:
/// static constexpr const char kTypeDescription[] = "<Description>";
template <typename DerivedTy, typename T>
class Defaulting {
public:
using ReferrentTy = T;
/// Type casters require the type to be default constructible, but using
/// such an instance is illegal.
Defaulting() = default;
Defaulting(ReferrentTy &referrent) : referrent(&referrent) {}
ReferrentTy *get() { return referrent; }
ReferrentTy *operator->() { return referrent; }
private:
ReferrentTy *referrent = nullptr;
};
} // namespace python
} // namespace mlir
[mlir][Python] Context managers for Context, InsertionPoint, Location. * Finishes support for Context, InsertionPoint and Location to be carried by the thread using context managers. * Introduces type casters and utilities so that DefaultPyMlirContext and DefaultPyLocation in method signatures does the right thing (allows explicit or gets from the thread context). * Extend the rules for the thread context stack to handle nesting, appropriately inheriting and clearing depending on whether the context is the same. * Refactors all method signatures to follow the new convention on trailing parameters for defaulting parameters (loc, ip, context). When the objects are carried in the thread context, this allows most explicit uses of these values to be elided. * Removes the style guide section on putting accessors to construct global objects on the PyMlirContext: this style fails to make good use of the new facility since it is often the only thing remaining needing an MlirContext. * Moves Module parse/creation from mlir.ir.Context to static methods on mlir.ir.Module. * Moves Context.create_operation to a static Operation.create method. * Moves Type parsing from mlir.ir.Context to static methods on mlir.ir.Type. * Moves Attribute parsing from mlir.ir.Context to static methods on mlir.ir.Attribute. * Move Location factory methods from mlir.ir.Context to static methods on mlir.ir.Location. * Refactors the std dialect fake "ODS" generated code to take advantage of the new scheme. Differential Revision: https://reviews.llvm.org/D90547
2020-10-31 23:40:25 -07:00
namespace pybind11 {
namespace detail {
template <typename DefaultingTy>
struct MlirDefaultingCaster {
PYBIND11_TYPE_CASTER(DefaultingTy, _(DefaultingTy::kTypeDescription));
bool load(pybind11::handle src, bool) {
if (src.is_none()) {
// Note that we do want an exception to propagate from here as it will be
// the most informative.
value = DefaultingTy{DefaultingTy::resolve()};
return true;
}
// Unlike many casters that chain, these casters are expected to always
// succeed, so instead of doing an isinstance check followed by a cast,
// just cast in one step and handle the exception. Returning false (vs
// letting the exception propagate) causes higher level signature parsing
// code to produce nice error messages (other than "Cannot cast...").
try {
value = DefaultingTy{
pybind11::cast<typename DefaultingTy::ReferrentTy &>(src)};
return true;
} catch (std::exception &e) {
return false;
}
}
static handle cast(DefaultingTy src, return_value_policy policy,
handle parent) {
return pybind11::cast(src, policy);
}
};
template <typename T>
struct type_caster<llvm::Optional<T>> : optional_caster<llvm::Optional<T>> {};
} // namespace detail
} // namespace pybind11
#endif // MLIR_BINDINGS_PYTHON_PYBINDUTILS_H