1*f6aab3d8Srobert //===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===// 2*f6aab3d8Srobert // 3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information. 5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*f6aab3d8Srobert // 7*f6aab3d8Srobert //===----------------------------------------------------------------------===// 8*f6aab3d8Srobert 9*f6aab3d8Srobert #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 10*f6aab3d8Srobert #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 11*f6aab3d8Srobert 12*f6aab3d8Srobert #if LLDB_ENABLE_PYTHON 13*f6aab3d8Srobert 14*f6aab3d8Srobert #include <optional> 15*f6aab3d8Srobert #include <sstream> 16*f6aab3d8Srobert #include <tuple> 17*f6aab3d8Srobert #include <type_traits> 18*f6aab3d8Srobert #include <utility> 19*f6aab3d8Srobert 20*f6aab3d8Srobert #include "lldb/Host/Config.h" 21*f6aab3d8Srobert #include "lldb/Interpreter/ScriptedInterface.h" 22*f6aab3d8Srobert #include "lldb/Utility/DataBufferHeap.h" 23*f6aab3d8Srobert 24*f6aab3d8Srobert #include "PythonDataObjects.h" 25*f6aab3d8Srobert #include "SWIGPythonBridge.h" 26*f6aab3d8Srobert #include "ScriptInterpreterPythonImpl.h" 27*f6aab3d8Srobert 28*f6aab3d8Srobert namespace lldb_private { 29*f6aab3d8Srobert class ScriptInterpreterPythonImpl; 30*f6aab3d8Srobert class ScriptedPythonInterface : virtual public ScriptedInterface { 31*f6aab3d8Srobert public: 32*f6aab3d8Srobert ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); 33*f6aab3d8Srobert ~ScriptedPythonInterface() override = default; 34*f6aab3d8Srobert 35*f6aab3d8Srobert protected: 36*f6aab3d8Srobert template <typename T = StructuredData::ObjectSP> ExtractValueFromPythonObject(python::PythonObject & p,Status & error)37*f6aab3d8Srobert T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { 38*f6aab3d8Srobert return p.CreateStructuredObject(); 39*f6aab3d8Srobert } 40*f6aab3d8Srobert 41*f6aab3d8Srobert template <typename T = StructuredData::ObjectSP, typename... Args> Dispatch(llvm::StringRef method_name,Status & error,Args &&...args)42*f6aab3d8Srobert T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { 43*f6aab3d8Srobert using namespace python; 44*f6aab3d8Srobert using Locker = ScriptInterpreterPythonImpl::Locker; 45*f6aab3d8Srobert 46*f6aab3d8Srobert std::string caller_signature = 47*f6aab3d8Srobert llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + 48*f6aab3d8Srobert llvm::Twine(method_name) + llvm::Twine(")")) 49*f6aab3d8Srobert .str(); 50*f6aab3d8Srobert if (!m_object_instance_sp) 51*f6aab3d8Srobert return ErrorWithMessage<T>(caller_signature, "Python object ill-formed", 52*f6aab3d8Srobert error); 53*f6aab3d8Srobert 54*f6aab3d8Srobert Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 55*f6aab3d8Srobert Locker::FreeLock); 56*f6aab3d8Srobert 57*f6aab3d8Srobert PythonObject implementor(PyRefType::Borrowed, 58*f6aab3d8Srobert (PyObject *)m_object_instance_sp->GetValue()); 59*f6aab3d8Srobert 60*f6aab3d8Srobert if (!implementor.IsAllocated()) 61*f6aab3d8Srobert return ErrorWithMessage<T>(caller_signature, 62*f6aab3d8Srobert "Python implementor not allocated.", error); 63*f6aab3d8Srobert 64*f6aab3d8Srobert std::tuple<Args...> original_args = std::forward_as_tuple(args...); 65*f6aab3d8Srobert auto transformed_args = TransformArgs(original_args); 66*f6aab3d8Srobert 67*f6aab3d8Srobert llvm::Expected<PythonObject> expected_return_object = 68*f6aab3d8Srobert llvm::make_error<llvm::StringError>("Not initialized.", 69*f6aab3d8Srobert llvm::inconvertibleErrorCode()); 70*f6aab3d8Srobert std::apply( 71*f6aab3d8Srobert [&implementor, &method_name, &expected_return_object](auto &&...args) { 72*f6aab3d8Srobert llvm::consumeError(expected_return_object.takeError()); 73*f6aab3d8Srobert expected_return_object = 74*f6aab3d8Srobert implementor.CallMethod(method_name.data(), args...); 75*f6aab3d8Srobert }, 76*f6aab3d8Srobert transformed_args); 77*f6aab3d8Srobert 78*f6aab3d8Srobert if (llvm::Error e = expected_return_object.takeError()) { 79*f6aab3d8Srobert error.SetErrorString(llvm::toString(std::move(e)).c_str()); 80*f6aab3d8Srobert return ErrorWithMessage<T>(caller_signature, 81*f6aab3d8Srobert "Python method could not be called.", error); 82*f6aab3d8Srobert } 83*f6aab3d8Srobert 84*f6aab3d8Srobert PythonObject py_return = std::move(expected_return_object.get()); 85*f6aab3d8Srobert 86*f6aab3d8Srobert if (!py_return.IsAllocated()) 87*f6aab3d8Srobert return ErrorWithMessage<T>(caller_signature, "Returned object is null.", 88*f6aab3d8Srobert error); 89*f6aab3d8Srobert 90*f6aab3d8Srobert // Now that we called the python method with the transformed arguments, 91*f6aab3d8Srobert // we need to interate again over both the original and transformed 92*f6aab3d8Srobert // parameter pack, and transform back the parameter that were passed in 93*f6aab3d8Srobert // the original parameter pack as references or pointers. 94*f6aab3d8Srobert if (sizeof...(Args) > 0) 95*f6aab3d8Srobert if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) 96*f6aab3d8Srobert return ErrorWithMessage<T>( 97*f6aab3d8Srobert caller_signature, 98*f6aab3d8Srobert "Couldn't re-assign reference and pointer arguments.", error); 99*f6aab3d8Srobert 100*f6aab3d8Srobert return ExtractValueFromPythonObject<T>(py_return, error); 101*f6aab3d8Srobert } 102*f6aab3d8Srobert 103*f6aab3d8Srobert template <typename... Args> GetStatusFromMethod(llvm::StringRef method_name,Args &&...args)104*f6aab3d8Srobert Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { 105*f6aab3d8Srobert Status error; 106*f6aab3d8Srobert Dispatch<Status>(method_name, error, std::forward<Args>(args)...); 107*f6aab3d8Srobert 108*f6aab3d8Srobert return error; 109*f6aab3d8Srobert } 110*f6aab3d8Srobert Transform(T object)111*f6aab3d8Srobert template <typename T> T Transform(T object) { 112*f6aab3d8Srobert // No Transformation for generic usage 113*f6aab3d8Srobert return {object}; 114*f6aab3d8Srobert } 115*f6aab3d8Srobert Transform(Status arg)116*f6aab3d8Srobert python::PythonObject Transform(Status arg) { 117*f6aab3d8Srobert return python::ToSWIGWrapper(arg); 118*f6aab3d8Srobert } 119*f6aab3d8Srobert 120*f6aab3d8Srobert template <typename T, typename U> ReverseTransform(T & original_arg,U transformed_arg,Status & error)121*f6aab3d8Srobert void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { 122*f6aab3d8Srobert // If U is not a PythonObject, don't touch it! 123*f6aab3d8Srobert return; 124*f6aab3d8Srobert } 125*f6aab3d8Srobert 126*f6aab3d8Srobert template <typename T> ReverseTransform(T & original_arg,python::PythonObject transformed_arg,Status & error)127*f6aab3d8Srobert void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, 128*f6aab3d8Srobert Status &error) { 129*f6aab3d8Srobert original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); 130*f6aab3d8Srobert } 131*f6aab3d8Srobert 132*f6aab3d8Srobert template <std::size_t... I, typename... Args> TransformTuple(const std::tuple<Args...> & args,std::index_sequence<I...>)133*f6aab3d8Srobert auto TransformTuple(const std::tuple<Args...> &args, 134*f6aab3d8Srobert std::index_sequence<I...>) { 135*f6aab3d8Srobert return std::make_tuple(Transform(std::get<I>(args))...); 136*f6aab3d8Srobert } 137*f6aab3d8Srobert 138*f6aab3d8Srobert // This will iterate over the Dispatch parameter pack and replace in-place 139*f6aab3d8Srobert // every `lldb_private` argument that has a SB counterpart. 140*f6aab3d8Srobert template <typename... Args> TransformArgs(const std::tuple<Args...> & args)141*f6aab3d8Srobert auto TransformArgs(const std::tuple<Args...> &args) { 142*f6aab3d8Srobert return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); 143*f6aab3d8Srobert } 144*f6aab3d8Srobert 145*f6aab3d8Srobert template <typename T, typename U> TransformBack(T & original_arg,U transformed_arg,Status & error)146*f6aab3d8Srobert void TransformBack(T &original_arg, U transformed_arg, Status &error) { 147*f6aab3d8Srobert ReverseTransform(original_arg, transformed_arg, error); 148*f6aab3d8Srobert } 149*f6aab3d8Srobert 150*f6aab3d8Srobert template <std::size_t... I, typename... Ts, typename... Us> ReassignPtrsOrRefsArgs(std::tuple<Ts...> & original_args,std::tuple<Us...> & transformed_args,std::index_sequence<I...>)151*f6aab3d8Srobert bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 152*f6aab3d8Srobert std::tuple<Us...> &transformed_args, 153*f6aab3d8Srobert std::index_sequence<I...>) { 154*f6aab3d8Srobert Status error; 155*f6aab3d8Srobert (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), 156*f6aab3d8Srobert error), 157*f6aab3d8Srobert ...); 158*f6aab3d8Srobert return error.Success(); 159*f6aab3d8Srobert } 160*f6aab3d8Srobert 161*f6aab3d8Srobert template <typename... Ts, typename... Us> ReassignPtrsOrRefsArgs(std::tuple<Ts...> & original_args,std::tuple<Us...> & transformed_args)162*f6aab3d8Srobert bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 163*f6aab3d8Srobert std::tuple<Us...> &transformed_args) { 164*f6aab3d8Srobert if (sizeof...(Ts) != sizeof...(Us)) 165*f6aab3d8Srobert return false; 166*f6aab3d8Srobert 167*f6aab3d8Srobert return ReassignPtrsOrRefsArgs(original_args, transformed_args, 168*f6aab3d8Srobert std::make_index_sequence<sizeof...(Ts)>()); 169*f6aab3d8Srobert } 170*f6aab3d8Srobert 171*f6aab3d8Srobert template <typename T, typename... Args> FormatArgs(std::string & fmt,T arg,Args...args)172*f6aab3d8Srobert void FormatArgs(std::string &fmt, T arg, Args... args) const { 173*f6aab3d8Srobert FormatArgs(fmt, arg); 174*f6aab3d8Srobert FormatArgs(fmt, args...); 175*f6aab3d8Srobert } 176*f6aab3d8Srobert FormatArgs(std::string & fmt,T arg)177*f6aab3d8Srobert template <typename T> void FormatArgs(std::string &fmt, T arg) const { 178*f6aab3d8Srobert fmt += python::PythonFormat<T>::format; 179*f6aab3d8Srobert } 180*f6aab3d8Srobert FormatArgs(std::string & fmt)181*f6aab3d8Srobert void FormatArgs(std::string &fmt) const {} 182*f6aab3d8Srobert 183*f6aab3d8Srobert // The lifetime is managed by the ScriptInterpreter 184*f6aab3d8Srobert ScriptInterpreterPythonImpl &m_interpreter; 185*f6aab3d8Srobert }; 186*f6aab3d8Srobert 187*f6aab3d8Srobert template <> 188*f6aab3d8Srobert StructuredData::ArraySP 189*f6aab3d8Srobert ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( 190*f6aab3d8Srobert python::PythonObject &p, Status &error); 191*f6aab3d8Srobert 192*f6aab3d8Srobert template <> 193*f6aab3d8Srobert StructuredData::DictionarySP 194*f6aab3d8Srobert ScriptedPythonInterface::ExtractValueFromPythonObject< 195*f6aab3d8Srobert StructuredData::DictionarySP>(python::PythonObject &p, Status &error); 196*f6aab3d8Srobert 197*f6aab3d8Srobert template <> 198*f6aab3d8Srobert Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 199*f6aab3d8Srobert python::PythonObject &p, Status &error); 200*f6aab3d8Srobert 201*f6aab3d8Srobert template <> 202*f6aab3d8Srobert lldb::DataExtractorSP 203*f6aab3d8Srobert ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 204*f6aab3d8Srobert python::PythonObject &p, Status &error); 205*f6aab3d8Srobert 206*f6aab3d8Srobert template <> 207*f6aab3d8Srobert std::optional<MemoryRegionInfo> 208*f6aab3d8Srobert ScriptedPythonInterface::ExtractValueFromPythonObject< 209*f6aab3d8Srobert std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); 210*f6aab3d8Srobert 211*f6aab3d8Srobert } // namespace lldb_private 212*f6aab3d8Srobert 213*f6aab3d8Srobert #endif // LLDB_ENABLE_PYTHON 214*f6aab3d8Srobert #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 215