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 340cdf4915SStella Laurenzo void release() { executionEngine.ptr = nullptr; } 350cdf4915SStella Laurenzo pybind11::object getCapsule() { 360cdf4915SStella Laurenzo return py::reinterpret_steal<py::object>( 370cdf4915SStella Laurenzo mlirPythonExecutionEngineToCapsule(get())); 380cdf4915SStella Laurenzo } 390cdf4915SStella Laurenzo 400cdf4915SStella Laurenzo static pybind11::object createFromCapsule(pybind11::object capsule) { 410cdf4915SStella Laurenzo MlirExecutionEngine rawPm = 420cdf4915SStella Laurenzo mlirPythonCapsuleToExecutionEngine(capsule.ptr()); 430cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(rawPm)) 440cdf4915SStella Laurenzo throw py::error_already_set(); 450cdf4915SStella Laurenzo return py::cast(PyExecutionEngine(rawPm), py::return_value_policy::move); 460cdf4915SStella Laurenzo } 470cdf4915SStella Laurenzo 480cdf4915SStella Laurenzo private: 490cdf4915SStella Laurenzo MlirExecutionEngine executionEngine; 500cdf4915SStella Laurenzo }; 510cdf4915SStella Laurenzo 520cdf4915SStella Laurenzo } // anonymous namespace 530cdf4915SStella Laurenzo 540cdf4915SStella Laurenzo /// Create the `mlir.execution_engine` module here. 550cdf4915SStella Laurenzo PYBIND11_MODULE(_mlirExecutionEngine, m) { 560cdf4915SStella Laurenzo m.doc() = "MLIR Execution Engine"; 570cdf4915SStella Laurenzo 580cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 590cdf4915SStella Laurenzo // Mapping of the top-level PassManager 600cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 61*f05ff4f7SStella Laurenzo py::class_<PyExecutionEngine>(m, "ExecutionEngine", py::module_local()) 620cdf4915SStella Laurenzo .def(py::init<>([](MlirModule module, int optLevel, 630cdf4915SStella Laurenzo const std::vector<std::string> &sharedLibPaths) { 640cdf4915SStella Laurenzo llvm::SmallVector<MlirStringRef, 4> libPaths; 650cdf4915SStella Laurenzo for (const std::string &path : sharedLibPaths) 660cdf4915SStella Laurenzo libPaths.push_back({path.c_str(), path.length()}); 670cdf4915SStella Laurenzo MlirExecutionEngine executionEngine = mlirExecutionEngineCreate( 680cdf4915SStella Laurenzo module, optLevel, libPaths.size(), libPaths.data()); 690cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(executionEngine)) 700cdf4915SStella Laurenzo throw std::runtime_error( 710cdf4915SStella Laurenzo "Failure while creating the ExecutionEngine."); 720cdf4915SStella Laurenzo return new PyExecutionEngine(executionEngine); 730cdf4915SStella Laurenzo }), 740cdf4915SStella Laurenzo py::arg("module"), py::arg("opt_level") = 2, 750cdf4915SStella Laurenzo py::arg("shared_libs") = py::list(), 760cdf4915SStella Laurenzo "Create a new ExecutionEngine instance for the given Module. The " 770cdf4915SStella Laurenzo "module must contain only dialects that can be translated to LLVM. " 780cdf4915SStella Laurenzo "Perform transformations and code generation at the optimization " 790cdf4915SStella Laurenzo "level `opt_level` if specified, or otherwise at the default " 800cdf4915SStella Laurenzo "level of two (-O2). Load a list of libraries specified in " 810cdf4915SStella Laurenzo "`shared_libs`.") 820cdf4915SStella Laurenzo .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 830cdf4915SStella Laurenzo &PyExecutionEngine::getCapsule) 840cdf4915SStella Laurenzo .def("_testing_release", &PyExecutionEngine::release, 850cdf4915SStella Laurenzo "Releases (leaks) the backing ExecutionEngine (for testing purpose)") 860cdf4915SStella Laurenzo .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyExecutionEngine::createFromCapsule) 870cdf4915SStella Laurenzo .def( 880cdf4915SStella Laurenzo "raw_lookup", 890cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &func) { 900cdf4915SStella Laurenzo auto *res = mlirExecutionEngineLookup( 910cdf4915SStella Laurenzo executionEngine.get(), 920cdf4915SStella Laurenzo mlirStringRefCreate(func.c_str(), func.size())); 930cdf4915SStella Laurenzo return reinterpret_cast<uintptr_t>(res); 940cdf4915SStella Laurenzo }, 950cdf4915SStella Laurenzo "Lookup function `func` in the ExecutionEngine.") 960cdf4915SStella Laurenzo .def( 970cdf4915SStella Laurenzo "raw_register_runtime", 980cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &name, 990cdf4915SStella Laurenzo uintptr_t sym) { 1000cdf4915SStella Laurenzo mlirExecutionEngineRegisterSymbol( 1010cdf4915SStella Laurenzo executionEngine.get(), 1020cdf4915SStella Laurenzo mlirStringRefCreate(name.c_str(), name.size()), 1030cdf4915SStella Laurenzo reinterpret_cast<void *>(sym)); 1040cdf4915SStella Laurenzo }, 1050cdf4915SStella Laurenzo "Lookup function `func` in the ExecutionEngine.") 1060cdf4915SStella Laurenzo .def( 1070cdf4915SStella Laurenzo "dump_to_object_file", 1080cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &fileName) { 1090cdf4915SStella Laurenzo mlirExecutionEngineDumpToObjectFile( 1100cdf4915SStella Laurenzo executionEngine.get(), 1110cdf4915SStella Laurenzo mlirStringRefCreate(fileName.c_str(), fileName.size())); 1120cdf4915SStella Laurenzo }, 1130cdf4915SStella Laurenzo "Dump ExecutionEngine to an object file."); 1140cdf4915SStella Laurenzo } 115