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/ExecutionEngine.h" 10*5cd42747SPeter Hawkins #include "mlir/Bindings/Python/NanobindAdaptors.h" 11*5cd42747SPeter Hawkins #include "mlir/Bindings/Python/Nanobind.h" 120cdf4915SStella Laurenzo 13*5cd42747SPeter Hawkins namespace nb = nanobind; 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) {} 24ea2e83afSAdrian Kuegel PyExecutionEngine(PyExecutionEngine &&other) noexcept 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 34204d301bSSean Silva void release() { 35204d301bSSean Silva executionEngine.ptr = nullptr; 36204d301bSSean Silva referencedObjects.clear(); 37204d301bSSean Silva } 38*5cd42747SPeter Hawkins nb::object getCapsule() { 39*5cd42747SPeter Hawkins return nb::steal<nb::object>(mlirPythonExecutionEngineToCapsule(get())); 400cdf4915SStella Laurenzo } 410cdf4915SStella Laurenzo 42204d301bSSean Silva // Add an object to the list of referenced objects whose lifetime must exceed 43204d301bSSean Silva // those of the ExecutionEngine. 44*5cd42747SPeter Hawkins void addReferencedObject(const nb::object &obj) { 45204d301bSSean Silva referencedObjects.push_back(obj); 46204d301bSSean Silva } 47204d301bSSean Silva 48*5cd42747SPeter Hawkins static nb::object createFromCapsule(nb::object capsule) { 490cdf4915SStella Laurenzo MlirExecutionEngine rawPm = 500cdf4915SStella Laurenzo mlirPythonCapsuleToExecutionEngine(capsule.ptr()); 510cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(rawPm)) 52*5cd42747SPeter Hawkins throw nb::python_error(); 53*5cd42747SPeter Hawkins return nb::cast(PyExecutionEngine(rawPm), nb::rv_policy::move); 540cdf4915SStella Laurenzo } 550cdf4915SStella Laurenzo 560cdf4915SStella Laurenzo private: 570cdf4915SStella Laurenzo MlirExecutionEngine executionEngine; 58204d301bSSean Silva // We support Python ctypes closures as callbacks. Keep a list of the objects 59204d301bSSean Silva // so that they don't get garbage collected. (The ExecutionEngine itself 60204d301bSSean Silva // just holds raw pointers with no lifetime semantics). 61*5cd42747SPeter Hawkins std::vector<nb::object> referencedObjects; 620cdf4915SStella Laurenzo }; 630cdf4915SStella Laurenzo 64be0a7e9fSMehdi Amini } // namespace 650cdf4915SStella Laurenzo 660cdf4915SStella Laurenzo /// Create the `mlir.execution_engine` module here. 67*5cd42747SPeter Hawkins NB_MODULE(_mlirExecutionEngine, m) { 680cdf4915SStella Laurenzo m.doc() = "MLIR Execution Engine"; 690cdf4915SStella Laurenzo 700cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 710cdf4915SStella Laurenzo // Mapping of the top-level PassManager 720cdf4915SStella Laurenzo //---------------------------------------------------------------------------- 73*5cd42747SPeter Hawkins nb::class_<PyExecutionEngine>(m, "ExecutionEngine") 74*5cd42747SPeter Hawkins .def( 75*5cd42747SPeter Hawkins "__init__", 76*5cd42747SPeter Hawkins [](PyExecutionEngine &self, MlirModule module, int optLevel, 7795c083f5SDenys Shabalin const std::vector<std::string> &sharedLibPaths, 7895c083f5SDenys Shabalin bool enableObjectDump) { 790cdf4915SStella Laurenzo llvm::SmallVector<MlirStringRef, 4> libPaths; 800cdf4915SStella Laurenzo for (const std::string &path : sharedLibPaths) 810cdf4915SStella Laurenzo libPaths.push_back({path.c_str(), path.length()}); 8295c083f5SDenys Shabalin MlirExecutionEngine executionEngine = 8395c083f5SDenys Shabalin mlirExecutionEngineCreate(module, optLevel, libPaths.size(), 8495c083f5SDenys Shabalin libPaths.data(), enableObjectDump); 850cdf4915SStella Laurenzo if (mlirExecutionEngineIsNull(executionEngine)) 860cdf4915SStella Laurenzo throw std::runtime_error( 870cdf4915SStella Laurenzo "Failure while creating the ExecutionEngine."); 88*5cd42747SPeter Hawkins new (&self) PyExecutionEngine(executionEngine); 89*5cd42747SPeter Hawkins }, 90*5cd42747SPeter Hawkins nb::arg("module"), nb::arg("opt_level") = 2, 91*5cd42747SPeter Hawkins nb::arg("shared_libs") = nb::list(), 92*5cd42747SPeter Hawkins nb::arg("enable_object_dump") = true, 930cdf4915SStella Laurenzo "Create a new ExecutionEngine instance for the given Module. The " 940cdf4915SStella Laurenzo "module must contain only dialects that can be translated to LLVM. " 950cdf4915SStella Laurenzo "Perform transformations and code generation at the optimization " 960cdf4915SStella Laurenzo "level `opt_level` if specified, or otherwise at the default " 970cdf4915SStella Laurenzo "level of two (-O2). Load a list of libraries specified in " 980cdf4915SStella Laurenzo "`shared_libs`.") 99*5cd42747SPeter Hawkins .def_prop_ro(MLIR_PYTHON_CAPI_PTR_ATTR, &PyExecutionEngine::getCapsule) 1000cdf4915SStella Laurenzo .def("_testing_release", &PyExecutionEngine::release, 1010cdf4915SStella Laurenzo "Releases (leaks) the backing ExecutionEngine (for testing purpose)") 1020cdf4915SStella Laurenzo .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyExecutionEngine::createFromCapsule) 1030cdf4915SStella Laurenzo .def( 1040cdf4915SStella Laurenzo "raw_lookup", 1050cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &func) { 106106f3074STres Popp auto *res = mlirExecutionEngineLookupPacked( 1070cdf4915SStella Laurenzo executionEngine.get(), 1080cdf4915SStella Laurenzo mlirStringRefCreate(func.c_str(), func.size())); 1090cdf4915SStella Laurenzo return reinterpret_cast<uintptr_t>(res); 1100cdf4915SStella Laurenzo }, 111*5cd42747SPeter Hawkins nb::arg("func_name"), 1120cdf4915SStella Laurenzo "Lookup function `func` in the ExecutionEngine.") 1130cdf4915SStella Laurenzo .def( 1140cdf4915SStella Laurenzo "raw_register_runtime", 1150cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &name, 116*5cd42747SPeter Hawkins nb::object callbackObj) { 117204d301bSSean Silva executionEngine.addReferencedObject(callbackObj); 118204d301bSSean Silva uintptr_t rawSym = 119*5cd42747SPeter Hawkins nb::cast<uintptr_t>(nb::getattr(callbackObj, "value")); 1200cdf4915SStella Laurenzo mlirExecutionEngineRegisterSymbol( 1210cdf4915SStella Laurenzo executionEngine.get(), 1220cdf4915SStella Laurenzo mlirStringRefCreate(name.c_str(), name.size()), 123204d301bSSean Silva reinterpret_cast<void *>(rawSym)); 1240cdf4915SStella Laurenzo }, 125*5cd42747SPeter Hawkins nb::arg("name"), nb::arg("callback"), 126204d301bSSean Silva "Register `callback` as the runtime symbol `name`.") 1270cdf4915SStella Laurenzo .def( 1280cdf4915SStella Laurenzo "dump_to_object_file", 1290cdf4915SStella Laurenzo [](PyExecutionEngine &executionEngine, const std::string &fileName) { 1300cdf4915SStella Laurenzo mlirExecutionEngineDumpToObjectFile( 1310cdf4915SStella Laurenzo executionEngine.get(), 1320cdf4915SStella Laurenzo mlirStringRefCreate(fileName.c_str(), fileName.size())); 1330cdf4915SStella Laurenzo }, 134*5cd42747SPeter Hawkins nb::arg("file_name"), "Dump ExecutionEngine to an object file."); 1350cdf4915SStella Laurenzo } 136