[Lldb-commits] [lldb] [DRAFT][lldb][rpc] Upstream RPC Client Library Emitters (PR #147655)

via lldb-commits lldb-commits at lists.llvm.org
Tue Jul 8 22:42:56 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Chelsea Cassanova (chelcassanova)

<details>
<summary>Changes</summary>

This commit upstreams the client side emitters for the lldb-rpc-gen tool alongside tests for its functionality and heuristics.

https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804

---

Patch is 55.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/147655.diff


17 Files Affected:

- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckArrayPointer.h (+20) 
- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstCharPtrPtrWithLen.h (+19) 
- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstSBRef.h (+19) 
- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckNonConstSBRef.h (+20) 
- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckSBPointer.h (+21) 
- (added) lldb/test/Shell/RPC/Generator/Inputs/Client/CheckVoidPtr.h (+19) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckArrayPointer.test (+11) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstCharPtrPtrWithLen.test (+10) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstSBRef.test (+14) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckNonConstSBRef.test (+13) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckSBPointer.test (+15) 
- (added) lldb/test/Shell/RPC/Generator/Tests/Client/CheckVoidPtr.test (+10) 
- (added) lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.cpp (+124) 
- (added) lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.h (+44) 
- (added) lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibrarySourceEmitter.cpp (+542) 
- (added) lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibrarySourceEmitter.h (+92) 
- (added) lldb/tools/lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp (+414) 


``````````diff
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckArrayPointer.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckArrayPointer.h
new file mode 100644
index 0000000000000..18ec92a976b8a
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckArrayPointer.h
@@ -0,0 +1,20 @@
+#ifndef LLDB_API_SBRPC_CHECKARRAYPTR_H
+#define LLDB_API_SBRPC_CHECKARRAYPTR_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKARRAYPTR {
+public:
+  // Pointers to arrays followed by length must use a
+  // Bytes object constructed using that pointer and the sizeof()
+  // the array object.
+  int CheckArrayPtr(uint64_t *array, size_t array_len);
+
+}; // class SBRPC_CHECKARRAYPTR
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKARRAYPTR_H
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstCharPtrPtrWithLen.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstCharPtrPtrWithLen.h
new file mode 100644
index 0000000000000..fa64492cf5aa7
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstCharPtrPtrWithLen.h
@@ -0,0 +1,19 @@
+#ifndef LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
+#define LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKCONSTCHARPTRPTRWITHLEN {
+public:
+  // const char ** followed by len must use a StringList
+  // when being encoded.
+  int CheckConstCharPtrPtrWithLen(const char **arg1, size_t len);
+
+}; // class SBRPC_CHECKCONSTCHARPTRPTRWITHLEN
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstSBRef.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstSBRef.h
new file mode 100644
index 0000000000000..153fdad60a494
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckConstSBRef.h
@@ -0,0 +1,19 @@
+#ifndef LLDB_API_SBRPC_CHECKCONSTSBREF_H
+#define LLDB_API_SBRPC_CHECKCONSTSBREF_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKCONSTSBREF {
+public:
+  // Const references to SB classes should be encoded as usual without
+  // needing to create a new object with its own connection.
+  int CheckConstSBRef(const SBDebugger &debugger_ref);
+
+}; // class SBRPC_CHECKCONSTSBREF
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKCONSTSBREF_H
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckNonConstSBRef.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckNonConstSBRef.h
new file mode 100644
index 0000000000000..90ee3d3a7fbd6
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckNonConstSBRef.h
@@ -0,0 +1,20 @@
+#ifndef LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
+#define LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKNONCONSTSBREF {
+public:
+  // Non-const references to SB classes will have new objects
+  // of that class constructed with the connection as the first parameter
+  // before being encoded if their existing connection is invalid.
+  int CheckNonConstSBRef(SBDebugger &debugger_ref);
+
+}; // class SBRPC_CHECKNONCONSTSBREF
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckSBPointer.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckSBPointer.h
new file mode 100644
index 0000000000000..d9b7efa820f53
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckSBPointer.h
@@ -0,0 +1,21 @@
+#ifndef LLDB_API_SBRPC_CHECKSBPTR_H
+#define LLDB_API_SBRPC_CHECKSBPTR_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKSBPTR {
+public:
+  // Pointers to SB objects must be checked to
+  // see if they're null. If so, then a new object of the given
+  // class must be created and encoded. Otherwise, the original
+  // parameter will be encoded.
+  int CheckSBPtr(SBDebugger *debugger_ptr);
+
+}; // class SBRPC_CHECKSBPTR
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKSBPTR_H
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckVoidPtr.h b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckVoidPtr.h
new file mode 100644
index 0000000000000..fa6484fc8d7cd
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/Client/CheckVoidPtr.h
@@ -0,0 +1,19 @@
+#ifndef LLDB_API_SBRPC_CHECKVOIDPTR_H
+#define LLDB_API_SBRPC_CHECKVOIDPTR_H
+
+#include <cstddef>
+#include <cstdio>
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+class LLDB_API SBRPC_CHECKVOIDPTR {
+public:
+  // void * followed by length must use a Bytes object
+  // when being encoded.
+  int CheckVoidPtr(void *buf, size_t len);
+
+}; // class SBRPC_CHECKVOIDPTR
+} // namespace lldb
+
+#endif // LLDB_API_SBRPC_CHECKVOIDPTR_H
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckArrayPointer.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckArrayPointer.test
new file mode 100644
index 0000000000000..1b58b389d612e
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckArrayPointer.test
@@ -0,0 +1,11 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckArrayPointer.h
+
+RUN: cat %t/lib/CheckArrayPointer.cpp | FileCheck %s
+
+# Pointers to arrays followed by length must use a
+# Bytes object constructed using that pointer and the sizeof()
+# the array object.
+CHECK: lldb_rpc::SBRPC_CHECKARRAYPTR::CheckArrayPtr
+CHECK: Bytes array_buffer(array, sizeof(uint64_t));
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstCharPtrPtrWithLen.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstCharPtrPtrWithLen.test
new file mode 100644
index 0000000000000..84d18c95fa7d2
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstCharPtrPtrWithLen.test
@@ -0,0 +1,10 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstCharPtrPtrWithLen.h
+
+RUN: cat %t/lib/CheckConstCharPtrPtrWithLen.cpp | FileCheck %s
+
+# const char ** followed by len must use a StringList
+# when being encoded.
+CHECK: lldb_rpc::SBRPC_CHECKCONSTCHARPTRPTRWITHLEN::CheckConstCharPtrPtrWithLen
+CHECK: StringList arg1_list
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstSBRef.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstSBRef.test
new file mode 100644
index 0000000000000..9b10d1711a9bc
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstSBRef.test
@@ -0,0 +1,14 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstSBRef.h
+
+RUN: cat %t/lib/CheckConstSBRef.cpp | FileCheck %s
+
+# Const references to SB classes should be encoded as usual without
+# needing to create a new object with its own connection. Here
+# we're checking to make sure that the given SB object ref will get
+# encoded immediately after the previous argument gets encoded without
+# anything happening in between.
+CHECK: lldb_rpc::SBRPC_CHECKCONSTSBREF::CheckConstSBRef
+CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *this);
+CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref)
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckNonConstSBRef.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckNonConstSBRef.test
new file mode 100644
index 0000000000000..d396e927b46d2
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckNonConstSBRef.test
@@ -0,0 +1,13 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckNonConstSBRef.h
+
+RUN: cat %t/lib/CheckNonConstSBRef.cpp | FileCheck %s
+
+# Non-const references to SB classes will have new objects
+# of that class constructed with the connection as the first parameter
+# before being encoded if their existing connection is invalid.
+CHECK: lldb_rpc::SBRPC_CHECKNONCONSTSBREF::CheckNonConstSBRef
+CHECK: if (connection_sp && !debugger_ref.ObjectRefIsValid())
+CHECK:     debugger_ref = lldb_rpc::SBDebugger(connection_sp);
+CHECK:   RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref);
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckSBPointer.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckSBPointer.test
new file mode 100644
index 0000000000000..5f355138182a8
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckSBPointer.test
@@ -0,0 +1,15 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckSBPointer.h
+
+RUN: cat %t/lib/CheckSBPointer.cpp | FileCheck %s
+
+# Pointers to SB objects must be checked to
+# see if they're null. If so, then a new object of the given
+# class must be created and encoded. Otherwise, the original
+# parameter will be encoded.
+CHECK: lldb_rpc::SBRPC_CHECKSBPTR::CheckSBPtr
+CHECK: if (debugger_ptr)
+CHECK:   RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *debugger_ptr);
+CHECK: else
+CHECK:    RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, rpc::ObjectRef(ObjectRefGetConnectionID(), eClass_lldb_SBDebugger, LLDB_RPC_INVALID_OBJECT_ID));
diff --git a/lldb/test/Shell/RPC/Generator/Tests/Client/CheckVoidPtr.test b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckVoidPtr.test
new file mode 100644
index 0000000000000..9907126a28fa6
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/Client/CheckVoidPtr.test
@@ -0,0 +1,10 @@
+RUN: mkdir -p %t/server
+RUN: mkdir -p %t/lib
+RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckVoidPtr.h
+
+RUN: cat %t/lib/CheckVoidPtr.cpp | FileCheck %s
+
+# void * followed by length must use a Bytes object
+# when being encoded.
+CHECK: lldb_rpc::SBRPC_CHECKVOIDPTR::CheckVoidPtr
+CHECK: Bytes buf_buffer(buf, len);
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.cpp b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.cpp
new file mode 100644
index 0000000000000..9537b490856f1
--- /dev/null
+++ b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.cpp
@@ -0,0 +1,124 @@
+#include "RPCLibraryHeaderEmitter.h"
+#include "RPCCommon.h"
+
+#include "clang/AST/AST.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace lldb_rpc_gen;
+
+void RPCLibraryHeaderEmitter::StartClass(std::string ClassName) {
+  CurrentClass = std::move(ClassName);
+  std::string BaseClass =
+      lldb_rpc_gen::SBClassInheritsFromObjectRef(CurrentClass)
+          ? "ObjectRef"
+          : "LocalObjectRef";
+  EmitLine("class " + CurrentClass + " : public rpc::" + BaseClass + " {");
+  EmitLine("public:");
+  IndentLevel++;
+  if (lldb_rpc_gen::SBClassRequiresDefaultCtor(CurrentClass))
+    EmitLine(CurrentClass + "();");
+
+  // NOTE: There's currently only one RPC-specific extension that is actually
+  // used AFAICT. We can generalize this if we need more.
+  if (CurrentClass == "SBDebugger")
+    EmitLine("int SetIOFile(const char *path);");
+}
+
+void RPCLibraryHeaderEmitter::EndClass() {
+  if (lldb_rpc_gen::SBClassRequiresCopyCtorAssign(CurrentClass)) {
+    if (!CopyCtorEmitted)
+      EmitLine(CurrentClass + "(const lldb_rpc::" + CurrentClass + " &rhs);");
+    if (!CopyAssignEmitted)
+      EmitLine(CurrentClass + " &operator=(const lldb_rpc::" + CurrentClass +
+               " &rhs);");
+  }
+  if (!MoveCtorEmitted)
+    EmitLine(CurrentClass + "(lldb_rpc::" + CurrentClass + " &&rhs);");
+  if (!MoveAssignEmitted)
+    EmitLine(CurrentClass + " &operator=(" + CurrentClass + " &&rhs);");
+
+  IndentLevel--;
+  EmitLine("}; // class " + CurrentClass);
+  CurrentClass.clear();
+}
+
+void RPCLibraryHeaderEmitter::EmitMethod(const Method &method) {
+  std::string DeclarationLine;
+  llvm::raw_string_ostream DeclarationLineStream(DeclarationLine);
+
+  if (method.IsCopyCtor)
+    CopyCtorEmitted = true;
+  else if (method.IsCopyAssign)
+    CopyAssignEmitted = true;
+  else if (method.IsMoveCtor)
+    MoveCtorEmitted = true;
+  else if (method.IsMoveAssign)
+    MoveAssignEmitted = true;
+
+  if (method.IsExplicitCtorOrConversionMethod)
+    DeclarationLineStream << "explicit ";
+  else if (!method.IsInstance)
+    DeclarationLineStream << "static ";
+
+  if (!method.IsDtor && !method.IsConversionMethod && !method.IsCtor)
+    DeclarationLineStream << lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
+                                 method.ReturnType.getAsString(method.Policy))
+                          << " ";
+  DeclarationLineStream << method.BaseName << "("
+                        << method.CreateParamListAsString(
+                               eLibrary, /*IncludeDefaultValue = */ true)
+                        << ")";
+  if (method.IsConst)
+    DeclarationLineStream << " const";
+  DeclarationLineStream << ";";
+
+  EmitLine(DeclarationLine);
+}
+
+void RPCLibraryHeaderEmitter::EmitEnum(EnumDecl *E) {
+  // NOTE: All of the enumerations embedded in SB classes are currently
+  // anonymous and backed by an unsigned int.
+  EmitLine("enum : unsigned {");
+  IndentLevel++;
+  for (const EnumConstantDecl *EC : E->enumerators()) {
+    std::string EnumValue = EC->getNameAsString();
+    SmallString<16> ValueStr;
+    EC->getInitVal().toString(ValueStr);
+    EnumValue += " = " + ValueStr.str().str() + ", ";
+    EmitLine(EnumValue);
+  }
+
+  IndentLevel--;
+  EmitLine("};");
+}
+
+std::string RPCLibraryHeaderEmitter::GetHeaderGuard() {
+  const std::string UpperFilenameNoExt =
+      llvm::sys::path::stem(
+          llvm::sys::path::filename(OutputFile->getFilename()))
+          .upper();
+  return "GENERATED_LLDB_RPC_LIBRARY_" + UpperFilenameNoExt + "_H";
+}
+
+void RPCLibraryHeaderEmitter::Begin() {
+  const std::string HeaderGuard = GetHeaderGuard();
+  EmitLine("#ifndef " + HeaderGuard);
+  EmitLine("#define " + HeaderGuard);
+  EmitLine("");
+  EmitLine("#include <lldb-rpc/common/RPCPublic.h>");
+  EmitLine("#include \"SBDefines.h\"");
+  EmitLine("#include \"LLDBRPC.h\"");
+  EmitLine("");
+  EmitLine("namespace lldb_rpc {");
+}
+
+void RPCLibraryHeaderEmitter::End() {
+  EmitLine("} // namespace lldb_rpc");
+  EmitLine("#endif // " + GetHeaderGuard());
+}
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.h b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.h
new file mode 100644
index 0000000000000..b9f22585c7955
--- /dev/null
+++ b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.h
@@ -0,0 +1,44 @@
+#ifndef LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H
+#define LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H
+
+#include "RPCCommon.h"
+
+#include "clang/AST/AST.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace clang;
+
+namespace lldb_rpc_gen {
+
+class RPCLibraryHeaderEmitter : public FileEmitter {
+public:
+  RPCLibraryHeaderEmitter(std::unique_ptr<llvm::ToolOutputFile> &&OutputFile)
+      : FileEmitter(std::move(OutputFile)), CurrentClass() {
+    Begin();
+  }
+
+  ~RPCLibraryHeaderEmitter() { End(); }
+
+  void StartClass(std::string ClassName);
+
+  void EndClass();
+
+  void EmitMethod(const Method &method);
+
+  void EmitEnum(EnumDecl *E);
+
+private:
+  std::string GetHeaderGuard();
+
+  void Begin();
+
+  void End();
+
+  std::string CurrentClass;
+  bool CopyCtorEmitted = false;
+  bool CopyAssignEmitted = false;
+  bool MoveCtorEmitted = false;
+  bool MoveAssignEmitted = false;
+};
+} // namespace lldb_rpc_gen
+#endif // LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibrarySourceEmitter.cpp b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibrarySourceEmitter.cpp
new file mode 100644
index 0000000000000..571fedc6edcce
--- /dev/null
+++ b/lldb/tools/lldb-rpc/lldb-rpc-gen/client/RPCLibrarySourceEmitter.cpp
@@ -0,0 +1,542 @@
+#include "RPCLibrarySourceEmitter.h"
+#include "RPCCommon.h"
+
+#include "clang/AST/AST.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace clang;
+using namespace lldb_rpc_gen;
+
+static constexpr llvm::StringRef ReturnVariableName("__result");
+
+// This map stores any method that needs custom logic with a struct that
+// tells us where the logic needs to be inserted and what code needs to be
+// inserted. The code here is stored as a raw string literal.
+const llvm::StringMap<RPCLibrarySourceEmitter::CustomLogic>
+    CustomLogicForMethods = {
+        {"_ZN4lldb10SBDebugger6CreateEbPFvPKcPvES3_",
+         {RPCLibrarySourceEmitter::CustomLogicLocation::eAfterDecode, R"code(
+    // Now source the .lldbinit files manually since we can't rely on the
+    // LLDB.framework on the other side to have special support for sourcing the right file
+    // since it would try to source "~/.lldbinit-lldb-rpc-server" followed by
+    // "~/.lldbinit". We want it to try "~.lldbinit-%s" where %s is the
+    // current program basename followed by "~/.lldbinit".
+
+    if (source_init_files && __result.ObjectRefIsValid()) {
+      const char *program_basename = rpc::GetProgramBasename();
+      if (program_basename) {
+        char init_path[PATH_MAX];
+        snprintf(init_path, sizeof(init_path), "~/.lldbinit-%s",
+                 program_basename);
+        lldb_rpc::SBFileSpec program_init_file(connection, init_path, true);
+        if (program_init_file.Exists()) {
+          char command_str[PATH_MAX];
+          snprintf(command_str, sizeof(command_str),
+                   "command source -s 1 -c 1 -e 0 '%s'", init_path);
+          __result.HandleCommand(command_str);
+        } else {
+          __result.HandleCommand("command source -s 1 -c 1 -e 0 '~/.lldbinit'");
+        }
+      }
+    })code"}},
+};
+
+static std::string GetLocalObjectRefCtor(const std::string &ClassName) {
+  return "rpc::LocalObjectRef(LLDB_RPC_INVALID_CONNECTION_ID, eClass_lldb_" +
+         ClassName + ", LLDB_RPC_INVALID_OBJECT_ID)";
+}
+
+static std::string GetObjectRefCtor(const std::string &ClassName) {
+  return "rpc::ObjectRef(LLDB_RPC_INVALID_CONNECTION_ID, eClass_lldb_" +
+         ClassName + ", LLDB_RPC_INVALID_OBJECT_ID)";
+}
+
+void RPCLibrarySourceEmitter::EmitCopyCtor() {
+  EmitLine("lldb_rpc::" + CurrentClass + "::" + CurrentClass +
+           "(const lldb_rpc::" + CurrentClass + " &rhs) = default;");
+}
+
+void RPCLibrarySourceEmitter::EmitCopyAssign() {
+  EmitLine("lldb_rpc::" + CurrentClass + " &lldb_rpc::" + CurrentClass +
+           "::operator=(const lldb_rpc::" + CurrentClass + " &rhs) = default;");
+}
+
+void RPCLibrarySourceEmitter::EmitMoveCtor() {
+  EmitLine("lldb_rpc::" + CurrentClass + "::" + CurrentClass +
+           "(lldb_rpc::" + CurrentClass + " &&rhs) = default;");
+}
+
+void RPCLibrarySourceEmitter::EmitMoveAssign() {
+  EmitLine("lldb_rpc::" + CurrentClass + " &lldb_rpc::" + CurrentClass +
+           "::operator=(lldb_rpc::" + CurrentClass + " &&rhs) = default;");
+}
+
+void RPCLibrarySourceEmitter::EmitMethod(const Method &method) {
+  if (method.IsCopyCtor) {
+    CopyCtorEmitted = true;
+    EmitCopyCtor();
+    return;
+  } else if (method.IsCopyAssign) {
+    CopyAssignEmitted = true;
+    EmitCopyAssign();
+    return;
+  } else if (method.IsMoveCtor) {
+    MoveCtorEmitted = true;
+    EmitMoveCtor();
+    return;
+  } else if (method.IsMoveAssign) {
+    MoveAssignEmitted = true;
+    EmitMoveAssign();
+    return;
+  }
+
+  EmitCommentHeader(method);
+  EmitFunctionHeader(method);
+  EmitFunctionBody(method);
+  EmitFunctionFooter();
+}
+
+void RPCLibrarySourceEmitter::StartClass(std::string ClassName) {
+  CurrentClass = std::move(ClassName);
+  if (lldb_rpc_gen::SBClassRequiresDefaultCtor(CurrentClass)) {
+    std::string BaseClassCtor =
+        lldb_rpc_gen::SBClassInheritsFromObjectRef(CurrentClass)
+            ? GetObjectRefCtor(CurrentClass)
+            : GetLocalObjectRefCtor(CurrentClass);
+    EmitLine("lldb_rpc...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/147655


More information about the lldb-commits mailing list