10cdf4915SStella Laurenzo //===- ExecutionEngineModule.cpp - Python module for execution engine -----===// 20cdf4915SStella Laurenzo // 30cdf4915SStella Laurenzo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40cdf4915SStella Laurenzo // See https://llvm.org/LICENSE.txt for license information. 50cdf4915SStella Laurenzo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60cdf4915SStella Laurenzo // 70cdf4915SStella Laurenzo //===----------------------------------------------------------------------===// 80cdf4915SStella Laurenzo 90cdf4915SStella Laurenzo #include "mlir-c/Bindings/Python/Interop.h" 100cdf4915SStella Laurenzo #include "mlir-c/ExecutionEngine.h" 110cdf4915SStella Laurenzo #include "mlir/Bindings/Python/PybindAdaptors.h" 120cdf4915SStella Laurenzo 130cdf4915SStella Laurenzo namespace py = pybind11; 140cdf4915SStella Laurenzo using namespace mlir; 150cdf4915SStella Laurenzo using namespace mlir::python; 160cdf4915SStella Laurenzo 170cdf4915SStella Laurenzo namespace { 180cdf4915SStella Laurenzo 190cdf4915SStella Laurenzo /// Owning Wrapper around an ExecutionEngine. 200cdf4915SStella Laurenzo class PyExecutionEngine { 210cdf4915SStella Laurenzo public: 220cdf4915SStella Laurenzo PyExecutionEngine(MlirExecutionEngine executionEngine) 230cdf4915SStella Laurenzo : executionEngine(executionEngine) {} 240cdf4915SStella Laurenzo PyExecutionEngine(PyExecutionEngine &&other) 250cdf4915SStella Laurenzo : executionEngine(other.executionEngine) { 260cdf4915SStella Laurenzo other.executionEngine.ptr = nullptr; 270cdf4915SStella Laurenzo } 280cdf4915SStella Laurenzo ~PyExecutionEngine() { 290cdf4915SStella Laurenzo if (!mlirExecutionEngineIsNull(executionEngine)) 300cdf4915SStella Laurenzo mlirExecutionEngineDestroy(executionEngine); 310cdf4915SStella Laurenzo } 320cdf4915SStella Laurenzo MlirExecutionEngine get() { return executionEngine; } 330cdf4915SStella Laurenzo 34*204d301bSSean Silva void release() { 35*204d301bSSean Silva executionEngine.ptr = nullptr; 36*204d301bSSean Silva referencedObjects.clear(); 37*204d301bSSean Silva } 380cdf4915SStella Laurenzo pybind11::object getCapsule() { 390cdf4915SStella Laurenzo return py::reinterpret_steal<py::object>( 400cdf4915SStella Laurenzo mlirPythonExecutionEngineToCapsule(get())); 410cdf4915SStella Laurenzo } 420cdf4915SStella Laurenzo 43*204d301bSSean Silva // Add an object to the list of referenced objects whose lifetime must exceed 44*204d301bSSean Silva // those of the ExecutionEngine. 45*204d301bSSean Silva void addReferencedObject(pybind11::object obj) { 46*204d301bSSean Silva referencedObjects.push_back(obj); 47*204d301bSSean Silva } 48*204d301bSSean Silva 490cdf4915SStella Laurenzo static pybind11::object createFromCapsule(pybind11::object capsule) { 500cdf4915SStella Laurenzo MlirExecutionEngine rawPm = 510cdf4915SStella Laurenzo mlirPythonCapsuleToExecutionEngine(capsule.ptr()); 520cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(rawPm)) 530cdf4915SStella Laurenzo throw py::error_already_set(); 540cdf4915SStella Laurenzo return py::cast(PyExecutionEngine(rawPm), py::return_value_policy::move); 550cdf4915SStella Laurenzo } 560cdf4915SStella Laurenzo 570cdf4915SStella Laurenzo private: 580cdf4915SStella Laurenzo MlirExecutionEngine executionEngine; 59*204d301bSSean Silva // We support Python ctypes closures as callbacks. Keep a list of the objects 60*204d301bSSean Silva // so that they don't get garbage collected. (The ExecutionEngine itself 61*204d301bSSean Silva // just holds raw pointers with no lifetime semantics). 62*204d301bSSean Silva std::vector<py::object> referencedObjects; 630cdf4915SStella Laurenzo }; 640cdf4915SStella Laurenzo 650cdf4915SStella Laurenzo } // anonymous namespace 660cdf4915SStella Laurenzo 670cdf4915SStella Laurenzo /// Create the `mlir.execution_engine` module here. 680cdf4915SStella Laurenzo PYBIND11_MODULE(_mlirExecutionEngine, m) { 690cdf4915SStella Laurenzo m.doc() = "MLIR Execution Engine"; 700cdf4915SStella Laurenzo 710cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 720cdf4915SStella Laurenzo // Mapping of the top-level PassManager 730cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 74f05ff4f7SStella Laurenzo py::class_<PyExecutionEngine>(m, "ExecutionEngine", py::module_local()) 750cdf4915SStella Laurenzo .def(py::init<>([](MlirModule module, int optLevel, 760cdf4915SStella Laurenzo const std::vector<std::string> &sharedLibPaths) { 770cdf4915SStella Laurenzo llvm::SmallVector<MlirStringRef, 4> libPaths; 780cdf4915SStella Laurenzo for (const std::string &path : sharedLibPaths) 790cdf4915SStella Laurenzo libPaths.push_back({path.c_str(), path.length()}); 800cdf4915SStella Laurenzo MlirExecutionEngine executionEngine = mlirExecutionEngineCreate( 810cdf4915SStella Laurenzo module, optLevel, libPaths.size(), libPaths.data()); 820cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(executionEngine)) 830cdf4915SStella Laurenzo throw std::runtime_error( 840cdf4915SStella Laurenzo "Failure while creating the ExecutionEngine."); 850cdf4915SStella Laurenzo return new PyExecutionEngine(executionEngine); 860cdf4915SStella Laurenzo }), 870cdf4915SStella Laurenzo py::arg("module"), py::arg("opt_level") = 2, 880cdf4915SStella Laurenzo py::arg("shared_libs") = py::list(), 890cdf4915SStella Laurenzo "Create a new ExecutionEngine instance for the given Module. The " 900cdf4915SStella Laurenzo "module must contain only dialects that can be translated to LLVM. " 910cdf4915SStella Laurenzo "Perform transformations and code generation at the optimization " 920cdf4915SStella Laurenzo "level `opt_level` if specified, or otherwise at the default " 930cdf4915SStella Laurenzo "level of two (-O2). Load a list of libraries specified in " 940cdf4915SStella Laurenzo "`shared_libs`.") 950cdf4915SStella Laurenzo .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 960cdf4915SStella Laurenzo &PyExecutionEngine::getCapsule) 970cdf4915SStella Laurenzo .def("_testing_release", &PyExecutionEngine::release, 980cdf4915SStella Laurenzo "Releases (leaks) the backing ExecutionEngine (for testing purpose)") 990cdf4915SStella Laurenzo .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyExecutionEngine::createFromCapsule) 1000cdf4915SStella Laurenzo .def( 1010cdf4915SStella Laurenzo "raw_lookup", 1020cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &func) { 1030cdf4915SStella Laurenzo auto *res = mlirExecutionEngineLookup( 1040cdf4915SStella Laurenzo executionEngine.get(), 1050cdf4915SStella Laurenzo mlirStringRefCreate(func.c_str(), func.size())); 1060cdf4915SStella Laurenzo return reinterpret_cast<uintptr_t>(res); 1070cdf4915SStella Laurenzo }, 1080cdf4915SStella Laurenzo "Lookup function `func` in the ExecutionEngine.") 1090cdf4915SStella Laurenzo .def( 1100cdf4915SStella Laurenzo "raw_register_runtime", 1110cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &name, 112*204d301bSSean Silva py::object callbackObj) { 113*204d301bSSean Silva executionEngine.addReferencedObject(callbackObj); 114*204d301bSSean Silva uintptr_t rawSym = 115*204d301bSSean Silva py::cast<uintptr_t>(py::getattr(callbackObj, "value")); 1160cdf4915SStella Laurenzo mlirExecutionEngineRegisterSymbol( 1170cdf4915SStella Laurenzo executionEngine.get(), 1180cdf4915SStella Laurenzo mlirStringRefCreate(name.c_str(), name.size()), 119*204d301bSSean Silva reinterpret_cast<void *>(rawSym)); 1200cdf4915SStella Laurenzo }, 121*204d301bSSean Silva py::arg("name"), py::arg("callback"), 122*204d301bSSean Silva "Register `callback` as the runtime symbol `name`.") 1230cdf4915SStella Laurenzo .def( 1240cdf4915SStella Laurenzo "dump_to_object_file", 1250cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &fileName) { 1260cdf4915SStella Laurenzo mlirExecutionEngineDumpToObjectFile( 1270cdf4915SStella Laurenzo executionEngine.get(), 1280cdf4915SStella Laurenzo mlirStringRefCreate(fileName.c_str(), fileName.size())); 1290cdf4915SStella Laurenzo }, 1300cdf4915SStella Laurenzo "Dump ExecutionEngine to an object file."); 1310cdf4915SStella Laurenzo } 132