aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h152
1 files changed, 105 insertions, 47 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
index 7c2fadc21d42..01dc07b49737 100644
--- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
+++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
@@ -9,10 +9,15 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
-#include "lldb/Host/Config.h"
-
#if LLDB_ENABLE_PYTHON
+#include <optional>
+#include <sstream>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "lldb/Host/Config.h"
#include "lldb/Interpreter/ScriptedInterface.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -34,7 +39,7 @@ protected:
}
template <typename T = StructuredData::ObjectSP, typename... Args>
- T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
+ T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) {
using namespace python;
using Locker = ScriptInterpreterPythonImpl::Locker;
@@ -56,59 +61,112 @@ protected:
return ErrorWithMessage<T>(caller_signature,
"Python implementor not allocated.", error);
- PythonObject pmeth(
- PyRefType::Owned,
- PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
+ std::tuple<Args...> original_args = std::forward_as_tuple(args...);
+ auto transformed_args = TransformArgs(original_args);
+
+ llvm::Expected<PythonObject> expected_return_object =
+ llvm::make_error<llvm::StringError>("Not initialized.",
+ llvm::inconvertibleErrorCode());
+ std::apply(
+ [&implementor, &method_name, &expected_return_object](auto &&...args) {
+ llvm::consumeError(expected_return_object.takeError());
+ expected_return_object =
+ implementor.CallMethod(method_name.data(), args...);
+ },
+ transformed_args);
+
+ if (llvm::Error e = expected_return_object.takeError()) {
+ error.SetErrorString(llvm::toString(std::move(e)).c_str());
+ return ErrorWithMessage<T>(caller_signature,
+ "Python method could not be called.", error);
+ }
- if (PyErr_Occurred())
- PyErr_Clear();
+ PythonObject py_return = std::move(expected_return_object.get());
- if (!pmeth.IsAllocated())
- return ErrorWithMessage<T>(caller_signature,
- "Python method not allocated.", error);
+ if (!py_return.IsAllocated())
+ return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
+ error);
- if (PyCallable_Check(pmeth.get()) == 0) {
- if (PyErr_Occurred())
- PyErr_Clear();
- return ErrorWithMessage<T>(caller_signature,
- "Python method not callable.", error);
- }
+ // Now that we called the python method with the transformed arguments,
+ // we need to interate again over both the original and transformed
+ // parameter pack, and transform back the parameter that were passed in
+ // the original parameter pack as references or pointers.
+ if (sizeof...(Args) > 0)
+ if (!ReassignPtrsOrRefsArgs(original_args, transformed_args))
+ return ErrorWithMessage<T>(
+ caller_signature,
+ "Couldn't re-assign reference and pointer arguments.", error);
- if (PyErr_Occurred())
- PyErr_Clear();
+ return ExtractValueFromPythonObject<T>(py_return, error);
+ }
- // TODO: make `const char *` when removing support for Python 2.
- char *format = nullptr;
- std::string format_buffer;
+ template <typename... Args>
+ Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) {
+ Status error;
+ Dispatch<Status>(method_name, error, std::forward<Args>(args)...);
- if (sizeof...(Args) > 0) {
- FormatArgs(format_buffer, args...);
- // TODO: make `const char *` when removing support for Python 2.
- format = const_cast<char *>(format_buffer.c_str());
- }
+ return error;
+ }
- // TODO: make `const char *` when removing support for Python 2.
- PythonObject py_return(
- PyRefType::Owned,
- PyObject_CallMethod(implementor.get(),
- const_cast<char *>(method_name.data()), format,
- args...));
+ template <typename T> T Transform(T object) {
+ // No Transformation for generic usage
+ return {object};
+ }
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- return ErrorWithMessage<T>(caller_signature,
- "Python method could not be called.", error);
- }
+ python::PythonObject Transform(Status arg) {
+ return python::ToSWIGWrapper(arg);
+ }
- if (!py_return.IsAllocated())
- return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
- error);
+ template <typename T, typename U>
+ void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
+ // If U is not a PythonObject, don't touch it!
+ return;
+ }
- return ExtractValueFromPythonObject<T>(py_return, error);
+ template <typename T>
+ void ReverseTransform(T &original_arg, python::PythonObject transformed_arg,
+ Status &error) {
+ original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error);
+ }
+
+ template <std::size_t... I, typename... Args>
+ auto TransformTuple(const std::tuple<Args...> &args,
+ std::index_sequence<I...>) {
+ return std::make_tuple(Transform(std::get<I>(args))...);
+ }
+
+ // This will iterate over the Dispatch parameter pack and replace in-place
+ // every `lldb_private` argument that has a SB counterpart.
+ template <typename... Args>
+ auto TransformArgs(const std::tuple<Args...> &args) {
+ return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>());
+ }
+
+ template <typename T, typename U>
+ void TransformBack(T &original_arg, U transformed_arg, Status &error) {
+ ReverseTransform(original_arg, transformed_arg, error);
}
- Status GetStatusFromMethod(llvm::StringRef method_name);
+ template <std::size_t... I, typename... Ts, typename... Us>
+ bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
+ std::tuple<Us...> &transformed_args,
+ std::index_sequence<I...>) {
+ Status error;
+ (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args),
+ error),
+ ...);
+ return error.Success();
+ }
+
+ template <typename... Ts, typename... Us>
+ bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
+ std::tuple<Us...> &transformed_args) {
+ if (sizeof...(Ts) != sizeof...(Us))
+ return false;
+
+ return ReassignPtrsOrRefsArgs(original_args, transformed_args,
+ std::make_index_sequence<sizeof...(Ts)>());
+ }
template <typename T, typename... Args>
void FormatArgs(std::string &fmt, T arg, Args... args) const {
@@ -117,7 +175,7 @@ protected:
}
template <typename T> void FormatArgs(std::string &fmt, T arg) const {
- fmt += GetPythonValueFormatString(arg);
+ fmt += python::PythonFormat<T>::format;
}
void FormatArgs(std::string &fmt) const {}
@@ -146,9 +204,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
python::PythonObject &p, Status &error);
template <>
-llvm::Optional<MemoryRegionInfo>
+std::optional<MemoryRegionInfo>
ScriptedPythonInterface::ExtractValueFromPythonObject<
- llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
+ std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
} // namespace lldb_private