Reverts llvm/llvm-project#147417. Failing an assert: `lldb-rpc-gen: ../llvm-project/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp:361: void lldb_rpc_gen::RPCServerSourceEmitter::EmitMethodCallAndEncode(const Method &): Assertion `Pos != MethodsWithPointerReturnTypes.end() && "Unable to determine the size of the return buffer"' failed.`
This commit is contained in:
parent
c2a818f48b
commit
76a841a5e6
@ -323,6 +323,4 @@ else()
|
||||
set(LLDB_CAN_USE_DEBUGSERVER OFF)
|
||||
endif()
|
||||
|
||||
set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
|
||||
|
||||
include(LLDBGenerateConfig)
|
||||
|
@ -132,10 +132,6 @@ if(TARGET lldb-framework)
|
||||
add_lldb_test_dependency(lldb-framework)
|
||||
endif()
|
||||
|
||||
if (LLDB_BUILD_LLDBRPC)
|
||||
add_lldb_test_dependency(lldb-rpc-generate-sources)
|
||||
endif()
|
||||
|
||||
# Add dependencies that are not exported targets when building standalone.
|
||||
if(NOT LLDB_BUILT_STANDALONE)
|
||||
add_lldb_test_dependency(
|
||||
@ -253,8 +249,7 @@ llvm_canonicalize_cmake_booleans(
|
||||
LLDB_TEST_SHELL_DISABLE_REMOTE
|
||||
LLDB_TOOL_LLDB_SERVER_BUILD
|
||||
LLDB_USE_SYSTEM_DEBUGSERVER
|
||||
LLDB_IS_64_BITS
|
||||
LLDB_BUILD_LLDBRPC)
|
||||
LLDB_IS_64_BITS)
|
||||
|
||||
# Configure the individual test suites.
|
||||
add_subdirectory(API)
|
||||
|
@ -1,9 +0,0 @@
|
||||
RUN: %lldb-rpc-gen --output-dir=%t %S/../Inputs/SBDummy.h
|
||||
|
||||
RUN: ls %t | FileCheck %s
|
||||
|
||||
# We're just making sure that the tool emits the class names,
|
||||
# methods and skipped methods file in the output directory.
|
||||
CHECK: SBAPI.def
|
||||
CHECK: SBClasses.def
|
||||
CHECK: SkippedMethods.txt
|
@ -1,3 +0,0 @@
|
||||
# All tests for the tool need lldb-rpc-gen to be built.
|
||||
if not config.lldb_has_lldbrpc:
|
||||
config.unsupported = True
|
@ -156,16 +156,6 @@ def use_lldb_substitutions(config):
|
||||
extra_args=["platform"],
|
||||
unresolved="ignore",
|
||||
),
|
||||
ToolSubst(
|
||||
"%lldb-rpc-gen",
|
||||
command=FindTool("lldb-rpc-gen"),
|
||||
# We need the LLDB build directory root to pass into the tool, not the test build root.
|
||||
extra_args=[
|
||||
"-p " + config.lldb_build_directory + "/..",
|
||||
'--extra-arg="-resource-dir=' + config.clang_resource_dir + '"',
|
||||
],
|
||||
unresolved="ignore",
|
||||
),
|
||||
"lldb-test",
|
||||
"lldb-dap",
|
||||
ToolSubst(
|
||||
|
@ -33,7 +33,6 @@ config.lldb_build_directory = "@LLDB_TEST_BUILD_DIRECTORY@"
|
||||
config.have_lldb_server = @LLDB_TOOL_LLDB_SERVER_BUILD@
|
||||
config.lldb_system_debugserver = @LLDB_USE_SYSTEM_DEBUGSERVER@
|
||||
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||
config.lldb_has_lldbrpc = @LLDB_BUILD_LLDBRPC@
|
||||
# The shell tests use their own module caches.
|
||||
config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-shell")
|
||||
config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-shell")
|
||||
|
@ -10,9 +10,6 @@ add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)
|
||||
|
||||
add_lldb_tool_subdirectory(lldb-instr)
|
||||
add_lldb_tool_subdirectory(lldb-dap)
|
||||
if (LLDB_BUILD_LLDBRPC)
|
||||
add_lldb_tool_subdirectory(lldb-rpc)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
add_lldb_tool_subdirectory(darwin-debug)
|
||||
|
@ -1,22 +0,0 @@
|
||||
include(CheckCXXCompilerFlag)
|
||||
# Umbrella target for the entire framework is a default target.
|
||||
add_custom_target(lldb-rpc ALL)
|
||||
|
||||
if(LLDB_CODESIGN_IDENTITY)
|
||||
# Use explicit LLDB identity
|
||||
set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY})
|
||||
else()
|
||||
# Use explicit LLVM identity or default to ad-hoc signing if empty
|
||||
if(NOT LLVM_CODESIGNING_IDENTITY)
|
||||
set(LLVM_CODESIGNING_IDENTITY -)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# LLDBRPCGeneration.cmake needs the LLDB_RPC_GEN_EXE variable
|
||||
# which gets defined in the lldb-rpc-gen folder, so we're adding
|
||||
# this folder before we add that file.
|
||||
add_lldb_tool_subdirectory(lldb-rpc-gen)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCGeneration.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCHeaders.cmake)
|
||||
|
||||
add_dependencies(lldb-rpc lldb-rpc-generate-sources liblldbrpc-headers)
|
@ -1,75 +0,0 @@
|
||||
if (NOT DEFINED LLDB_RPC_GEN_EXE)
|
||||
message(FATAL_ERROR
|
||||
"Unable to generate lldb-rpc sources because LLDB_RPC_GEN_EXE is not
|
||||
defined. If you are cross-compiling, please build lldb-rpc-gen for your host
|
||||
platform.")
|
||||
endif()
|
||||
set(lldb_rpc_generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(lldb_rpc_server_generated_source_dir "${lldb_rpc_generated_dir}/server")
|
||||
|
||||
file(GLOB api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SB*.h)
|
||||
# We don't generate SBCommunication
|
||||
list(REMOVE_ITEM api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SBCommunication.h)
|
||||
# SBDefines.h is mostly definitions and forward declarations, nothing to
|
||||
# generate.
|
||||
list(REMOVE_ITEM api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SBDefines.h)
|
||||
|
||||
# Generate the list of byproducts. Note that we cannot just glob the files in
|
||||
# the directory with the generated sources because BYPRODUCTS needs to be known
|
||||
# at configure time but the files are generated at build time.
|
||||
set(lldb_rpc_gen_byproducts
|
||||
${lldb_rpc_generated_dir}/SBClasses.def
|
||||
${lldb_rpc_generated_dir}/SBAPI.def
|
||||
${lldb_rpc_generated_dir}/lldb.py
|
||||
${lldb_rpc_server_generated_source_dir}/SBAPI.h
|
||||
)
|
||||
|
||||
set(lldb_rpc_gen_server_impl_files)
|
||||
foreach(path ${api_headers})
|
||||
get_filename_component(filename_no_ext ${path} NAME_WLE)
|
||||
|
||||
set(server_header_file "Server_${filename_no_ext}.h")
|
||||
list(APPEND lldb_rpc_gen_byproducts "${lldb_rpc_server_generated_source_dir}/${server_header_file}")
|
||||
|
||||
set(server_impl_file "Server_${filename_no_ext}.cpp")
|
||||
list(APPEND lldb_rpc_gen_byproducts "${lldb_rpc_server_generated_source_dir}/${server_impl_file}")
|
||||
list(APPEND lldb_rpc_gen_server_impl_files "${lldb_rpc_server_generated_source_dir}/${server_impl_file}")
|
||||
|
||||
endforeach()
|
||||
|
||||
# Make sure that the clang-resource-dir is set correctly or else the tool will
|
||||
# fail to run. This is only needed when we do a standalone build.
|
||||
set(clang_resource_dir_arg)
|
||||
if (TARGET clang-resource-headers)
|
||||
set(clang_resource_headers_dir
|
||||
$<TARGET_PROPERTY:clang-resource-headers,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
set(clang_resource_dir_arg --extra-arg="-resource-dir=${clang_resource_headers_dir}/..")
|
||||
else()
|
||||
set(clang_resource_dir_arg --extra-arg="-resource-dir=${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${lldb_rpc_gen_byproducts}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
${lldb_rpc_generated_dir}
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
${lldb_rpc_server_generated_source_dir}
|
||||
|
||||
COMMAND ${LLDB_RPC_GEN_EXE}
|
||||
-p ${CMAKE_BINARY_DIR}
|
||||
--output-dir=${lldb_rpc_generated_dir}
|
||||
${clang_resource_dir_arg}
|
||||
--extra-arg="-USWIG"
|
||||
${api_headers}
|
||||
|
||||
DEPENDS ${LLDB_RPC_GEN_EXE} ${api_headers}
|
||||
COMMENT "Generating sources for lldb-rpc-server..."
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(lldb-rpc-generate-sources
|
||||
DEPENDS
|
||||
${lldb_rpc_gen_byproducts}
|
||||
lldb-sbapi-dwarf-enums)
|
||||
|
||||
add_dependencies(lldb-rpc-generate-sources clang-resource-headers)
|
@ -1,101 +0,0 @@
|
||||
set(derived_headers_location "${CMAKE_CURRENT_BINARY_DIR}/DerivedHeaders")
|
||||
|
||||
# Obtain the original headers from their staged location in the build directory.
|
||||
set(original_headers_location "${CMAKE_BINARY_DIR}/include/lldb")
|
||||
set(headers_to_process
|
||||
SBDefines.h
|
||||
lldb-defines.h
|
||||
lldb-enumerations.h
|
||||
lldb-types.h
|
||||
)
|
||||
|
||||
file(MAKE_DIRECTORY ${derived_headers_location})
|
||||
|
||||
# Take the original headers and convert them RPC as necessary using the conversion script.
|
||||
set(original_headers)
|
||||
set(derived_headers)
|
||||
foreach(header ${headers_to_process})
|
||||
set(original_header "${original_headers_location}/${header}")
|
||||
|
||||
get_filename_component(header_filename ${header} NAME)
|
||||
string(REPLACE "lldb-" "lldb-rpc-" rpc_header_filename "${header_filename}")
|
||||
set(derived_header "${derived_headers_location}/${rpc_header_filename}")
|
||||
|
||||
list(APPEND original_headers "${original_header}")
|
||||
list(APPEND derived_headers "${derived_header}")
|
||||
add_custom_command(OUTPUT ${derived_header}
|
||||
COMMAND ${Python3_EXECUTABLE} ${LLDB_SOURCE_DIR}/scripts/convert-lldb-header-to-rpc-header.py
|
||||
${original_header} ${derived_header}
|
||||
DEPENDS ${original_header}
|
||||
|
||||
COMMENT "Creating ${derived_header}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Do the same thing for any header files that were autogenerated.
|
||||
set(generated_headers_to_process
|
||||
API/SBLanguages.h
|
||||
)
|
||||
foreach(header ${generated_headers_to_process})
|
||||
set(original_header "${LLDB_OBJ_DIR}/include/lldb/${header}")
|
||||
|
||||
get_filename_component(header_filename ${header} NAME)
|
||||
string(REPLACE "lldb-" "lldb-rpc-" rpc_header_filename "${header_filename}")
|
||||
set(derived_header "${derived_headers_location}/${rpc_header_filename}")
|
||||
|
||||
list(APPEND original_headers "${original_header}")
|
||||
list(APPEND derived_headers "${derived_header}")
|
||||
add_custom_command(OUTPUT ${derived_header}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${original_header} ${derived_header}
|
||||
COMMAND ${Python3_EXECUTABLE} ${LLDB_SOURCE_DIR}/scripts/convert-lldb-header-to-rpc-header.py
|
||||
${original_header} ${derived_header}
|
||||
DEPENDS lldb-sbapi-dwarf-enums
|
||||
|
||||
COMMENT "Creating ${derived_header}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(copy-aux-rpc-headers DEPENDS ${derived_headers})
|
||||
add_dependencies(copy-aux-rpc-headers liblldb-header-staging)
|
||||
|
||||
list(APPEND public_headers
|
||||
${derived_headers_location}/SBDefines.h
|
||||
${derived_headers_location}/SBLanguages.h
|
||||
${derived_headers_location}/lldb-rpc-enumerations.h
|
||||
${derived_headers_location}/lldb-rpc-types.h
|
||||
${derived_headers_location}/lldb-rpc-defines.h
|
||||
)
|
||||
|
||||
# Collect and preprocess headers for the framework bundle
|
||||
set(version_header
|
||||
${derived_headers_location}/lldb-rpc-defines.h
|
||||
)
|
||||
|
||||
function(FixIncludePaths in subfolder out)
|
||||
get_filename_component(base_name ${in} NAME)
|
||||
set(parked_header ${CMAKE_CURRENT_BINARY_DIR}/ParkedHeaders/${subfolder}/${base_name})
|
||||
set(${out} ${parked_header} PARENT_SCOPE)
|
||||
find_program(unifdef_EXECUTABLE unifdef)
|
||||
|
||||
add_custom_command(OUTPUT ${parked_header}
|
||||
COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.py
|
||||
-f lldb_rpc -i ${in} -o ${parked_header} -p ${unifdef_EXECUTABLE} USWIG
|
||||
DEPENDS ${in}
|
||||
COMMENT "Fixing includes in ${in}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(preprocessed_headers)
|
||||
|
||||
# Apply include-paths fix and any version fix on all headers and park them.
|
||||
foreach(source_header ${public_headers})
|
||||
FixIncludePaths(${source_header} Headers parked_header)
|
||||
list(APPEND preprocessed_headers ${parked_header})
|
||||
endforeach()
|
||||
|
||||
# Wrap header preprocessing in a target, so liblldbrpc can depend on.
|
||||
add_custom_target(liblldbrpc-headers DEPENDS ${preprocessed_headers})
|
||||
add_dependencies(liblldbrpc-headers copy-aux-rpc-headers liblldb-header-staging)
|
||||
set_target_properties(liblldbrpc-headers PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ParkedHeaders
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
add_lldb_tool(lldb-rpc-gen
|
||||
RPCCommon.cpp
|
||||
server/RPCServerHeaderEmitter.cpp
|
||||
server/RPCServerSourceEmitter.cpp
|
||||
lldb-rpc-gen.cpp
|
||||
|
||||
CLANG_LIBS
|
||||
clangAST
|
||||
clangBasic
|
||||
clangCodeGen
|
||||
clangFrontend
|
||||
clangLex
|
||||
clangRewrite
|
||||
clangSerialization
|
||||
clangTooling
|
||||
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
||||
if (NOT DEFINED LLDB_RPC_GEN_EXE)
|
||||
set(LLDB_RPC_GEN_EXE $<TARGET_FILE:lldb-rpc-gen> CACHE STRING "Executable that generates lldb-rpc-server")
|
||||
endif()
|
@ -1,501 +0,0 @@
|
||||
//===-- RPCCommon.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RPCCommon.h"
|
||||
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/Mangle.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
// We intentionally do not generate some classes because they are currently
|
||||
// inconvenient, they aren't really used by most consumers, or we're not sure
|
||||
// why they exist.
|
||||
static constexpr llvm::StringRef DisallowedClasses[] = {
|
||||
"SBCommunication", // This class is pretty much unused by consumers, so we
|
||||
// skip it.
|
||||
"SBInputReader", // This class is pretty much unused by consumers, so we
|
||||
// skip it.
|
||||
"SBCommandPluginInterface", // This class uses virtual functions, and the SB
|
||||
// API should not have those, so we skip this
|
||||
// class.
|
||||
"SBCommand", // There's nothing too difficult about this one, but many of
|
||||
// its methods take a SBCommandPluginInterface pointer so
|
||||
// there's no reason to support this.
|
||||
};
|
||||
|
||||
// NOTE: In lldb-rpc-gen, we use mangled names when we need to work with
|
||||
// functions. We do this because we support many functions that have overloads,
|
||||
// and mangled names have no ambiguity which makes it easier to keep track of.
|
||||
// This is also possible since the LLDB SB API is stable.
|
||||
|
||||
// We intentionally avoid generating certain methods either because they are
|
||||
// difficult to support correctly or they aren't really used much from C++.
|
||||
// NOTE: These methods are marked as deprecated using LLDB_DEPRECATED.
|
||||
// Normally this macro defines to the deprecated annotation, but this
|
||||
// functionality is removed in SBDefines.h when generating SWIG bindings which
|
||||
// we use for testing. Because of this, there is no annotation for the tool to
|
||||
// pick up on so this list will be used while we have this restriction in
|
||||
// SBDefines.h.
|
||||
static constexpr llvm::StringRef DisallowedMethods[] = {
|
||||
// The threading functionality in SBHostOS is deprecated and thus we do not
|
||||
// generate them. It would be ideal to add the annotations to the methods
|
||||
// and then support not generating deprecated methods. However, without
|
||||
// annotations the generator generates most things correctly. This one is
|
||||
// problematic because it returns a pointer to an "opaque" structure
|
||||
// (thread_t) that is not `void *`, so special casing it is more effort than
|
||||
// it's worth.
|
||||
"_ZN4lldb8SBHostOS10ThreadJoinEP17_opaque_pthread_tPPvPNS_7SBErrorE",
|
||||
"_ZN4lldb8SBHostOS12ThreadCancelEP17_opaque_pthread_tPNS_7SBErrorE",
|
||||
"_ZN4lldb8SBHostOS12ThreadCreateEPKcPFPvS3_ES3_PNS_7SBErrorE",
|
||||
"_ZN4lldb8SBHostOS12ThreadDetachEP17_opaque_pthread_tPNS_7SBErrorE",
|
||||
"_ZN4lldb8SBHostOS13ThreadCreatedEPKc",
|
||||
};
|
||||
|
||||
static constexpr llvm::StringRef ClassesWithoutDefaultCtor[] = {
|
||||
"SBHostOS",
|
||||
"SBReproducer",
|
||||
};
|
||||
|
||||
static constexpr llvm::StringRef ClassesWithoutCopyOperations[] = {
|
||||
"SBHostOS",
|
||||
"SBReproducer",
|
||||
"SBStream",
|
||||
"SBProgress",
|
||||
};
|
||||
|
||||
static constexpr llvm::StringRef MethodsWithPointerPlusLen[] = {
|
||||
"_ZN4lldb6SBData11ReadRawDataERNS_7SBErrorEyPvm",
|
||||
"_ZN4lldb6SBData7SetDataERNS_7SBErrorEPKvmNS_9ByteOrderEh",
|
||||
"_ZN4lldb6SBData20SetDataWithOwnershipERNS_7SBErrorEPKvmNS_9ByteOrderEh",
|
||||
"_ZN4lldb6SBData25CreateDataFromUInt64ArrayENS_9ByteOrderEjPym",
|
||||
"_ZN4lldb6SBData25CreateDataFromUInt32ArrayENS_9ByteOrderEjPjm",
|
||||
"_ZN4lldb6SBData25CreateDataFromSInt64ArrayENS_9ByteOrderEjPxm",
|
||||
"_ZN4lldb6SBData25CreateDataFromSInt32ArrayENS_9ByteOrderEjPim",
|
||||
"_ZN4lldb6SBData25CreateDataFromDoubleArrayENS_9ByteOrderEjPdm",
|
||||
"_ZN4lldb6SBData22SetDataFromUInt64ArrayEPym",
|
||||
"_ZN4lldb6SBData22SetDataFromUInt32ArrayEPjm",
|
||||
"_ZN4lldb6SBData22SetDataFromSInt64ArrayEPxm",
|
||||
"_ZN4lldb6SBData22SetDataFromSInt32ArrayEPim",
|
||||
"_ZN4lldb6SBData22SetDataFromDoubleArrayEPdm",
|
||||
"_ZN4lldb10SBDebugger22GetDefaultArchitectureEPcm",
|
||||
"_ZN4lldb10SBDebugger13DispatchInputEPvPKvm",
|
||||
"_ZN4lldb10SBDebugger13DispatchInputEPKvm",
|
||||
"_ZN4lldb6SBFile4ReadEPhmPm",
|
||||
"_ZN4lldb6SBFile5WriteEPKhmPm",
|
||||
"_ZNK4lldb10SBFileSpec7GetPathEPcm",
|
||||
"_ZN4lldb10SBFileSpec11ResolvePathEPKcPcm",
|
||||
"_ZN4lldb8SBModule10GetVersionEPjj",
|
||||
"_ZN4lldb12SBModuleSpec12SetUUIDBytesEPKhm",
|
||||
"_ZNK4lldb9SBProcess9GetSTDOUTEPcm",
|
||||
"_ZNK4lldb9SBProcess9GetSTDERREPcm",
|
||||
"_ZNK4lldb9SBProcess19GetAsyncProfileDataEPcm",
|
||||
"_ZN4lldb9SBProcess10ReadMemoryEyPvmRNS_7SBErrorE",
|
||||
"_ZN4lldb9SBProcess11WriteMemoryEyPKvmRNS_7SBErrorE",
|
||||
"_ZN4lldb9SBProcess21ReadCStringFromMemoryEyPvmRNS_7SBErrorE",
|
||||
"_ZNK4lldb16SBStructuredData14GetStringValueEPcm",
|
||||
"_ZN4lldb8SBTarget23BreakpointCreateByNamesEPPKcjjRKNS_"
|
||||
"14SBFileSpecListES6_",
|
||||
"_ZN4lldb8SBTarget10ReadMemoryENS_9SBAddressEPvmRNS_7SBErrorE",
|
||||
"_ZN4lldb8SBTarget15GetInstructionsENS_9SBAddressEPKvm",
|
||||
"_ZN4lldb8SBTarget25GetInstructionsWithFlavorENS_9SBAddressEPKcPKvm",
|
||||
"_ZN4lldb8SBTarget15GetInstructionsEyPKvm",
|
||||
"_ZN4lldb8SBTarget25GetInstructionsWithFlavorEyPKcPKvm",
|
||||
"_ZN4lldb8SBThread18GetStopDescriptionEPcm",
|
||||
// The below mangled names are used for dummy methods in shell tests
|
||||
// that test the emitters' output. If you're adding any new mangled names
|
||||
// from the actual SB API to this list please add them above.
|
||||
"_ZN4lldb33SBRPC_"
|
||||
"CHECKCONSTCHARPTRPTRWITHLEN27CheckConstCharPtrPtrWithLenEPPKcm",
|
||||
"_ZN4lldb19SBRPC_CHECKARRAYPTR13CheckArrayPtrEPPKcm",
|
||||
"_ZN4lldb18SBRPC_CHECKVOIDPTR12CheckVoidPtrEPvm",
|
||||
};
|
||||
|
||||
// These classes inherit from rpc::ObjectRef directly (as opposed to
|
||||
// rpc::LocalObjectRef). Changing them from ObjectRef to LocalObjectRef is ABI
|
||||
// breaking, so we preserve that compatibility here.
|
||||
//
|
||||
// lldb-rpc-gen emits classes as LocalObjectRefs by default.
|
||||
//
|
||||
// FIXME: Does it matter which one it emits by default?
|
||||
static constexpr llvm::StringRef ClassesThatInheritFromObjectRef[] = {
|
||||
"SBAddress",
|
||||
"SBBreakpointName",
|
||||
"SBCommandInterpreter",
|
||||
"SBCommandReturnObject",
|
||||
"SBError",
|
||||
"SBExecutionContext",
|
||||
"SBExpressionOptions",
|
||||
"SBFileSpec",
|
||||
"SBFileSpecList",
|
||||
"SBFormat",
|
||||
"SBFunction",
|
||||
"SBHistoricalFrame",
|
||||
"SBHistoricalLineEntry",
|
||||
"SBHistoricalLineEntryList",
|
||||
"SBLineEntry",
|
||||
"SBStream",
|
||||
"SBStringList",
|
||||
"SBStructuredData",
|
||||
"SBSymbolContext",
|
||||
"SBSymbolContextList",
|
||||
"SBTypeMember",
|
||||
"SBTypeSummaryOptions",
|
||||
"SBValueList",
|
||||
};
|
||||
|
||||
QualType lldb_rpc_gen::GetUnderlyingType(QualType T) {
|
||||
QualType UnderlyingType;
|
||||
if (T->isPointerType())
|
||||
UnderlyingType = T->getPointeeType();
|
||||
else if (T->isReferenceType())
|
||||
UnderlyingType = T.getNonReferenceType();
|
||||
else
|
||||
UnderlyingType = T;
|
||||
|
||||
return UnderlyingType;
|
||||
}
|
||||
|
||||
QualType lldb_rpc_gen::GetUnqualifiedUnderlyingType(QualType T) {
|
||||
return GetUnderlyingType(T).getUnqualifiedType();
|
||||
}
|
||||
|
||||
std::string lldb_rpc_gen::GetMangledName(ASTContext &Context,
|
||||
CXXMethodDecl *MDecl) {
|
||||
std::string Mangled;
|
||||
llvm::raw_string_ostream MangledStream(Mangled);
|
||||
|
||||
GlobalDecl GDecl;
|
||||
if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(MDecl))
|
||||
GDecl = GlobalDecl(CtorDecl, Ctor_Complete);
|
||||
else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(MDecl))
|
||||
GDecl = GlobalDecl(DtorDecl, Dtor_Deleting);
|
||||
else
|
||||
GDecl = GlobalDecl(MDecl);
|
||||
|
||||
MangleContext *MC = Context.createMangleContext();
|
||||
MC->mangleName(GDecl, MangledStream);
|
||||
return Mangled;
|
||||
}
|
||||
|
||||
static auto CheckTypeForLLDBPrivate = [](const Type *Ty) {};
|
||||
bool lldb_rpc_gen::TypeIsFromLLDBPrivate(QualType T) {
|
||||
auto CheckTypeForLLDBPrivate = [](const Type *Ty) {
|
||||
if (!Ty)
|
||||
return false;
|
||||
const auto *CXXRDecl = Ty->getAsCXXRecordDecl();
|
||||
if (!CXXRDecl)
|
||||
return false;
|
||||
const auto *NSDecl =
|
||||
llvm::dyn_cast<NamespaceDecl>(CXXRDecl->getDeclContext());
|
||||
if (!NSDecl)
|
||||
return false;
|
||||
return NSDecl->getName() == "lldb_private";
|
||||
};
|
||||
|
||||
// First, get the underlying type (remove qualifications and strip off any
|
||||
// pointers/references). Then we'll need to desugar this type. This will
|
||||
// remove things like typedefs, so instead of seeing "lldb::DebuggerSP" we'll
|
||||
// actually see something like "std::shared_ptr<lldb_private::Debugger>".
|
||||
QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
|
||||
const Type *DesugaredType =
|
||||
UnqualifiedUnderlyingType->getUnqualifiedDesugaredType();
|
||||
assert(DesugaredType && "DesugaredType from a valid Type is nullptr!");
|
||||
|
||||
// Check the type itself.
|
||||
if (CheckTypeForLLDBPrivate(DesugaredType))
|
||||
return true;
|
||||
|
||||
// If that didn't work, it's possible that the type has a template argument
|
||||
// that is an lldb_private type.
|
||||
if (const auto *TemplateSDecl =
|
||||
llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(
|
||||
DesugaredType->getAsCXXRecordDecl())) {
|
||||
for (const TemplateArgument &TA :
|
||||
TemplateSDecl->getTemplateArgs().asArray()) {
|
||||
if (TA.getKind() != TemplateArgument::Type)
|
||||
continue;
|
||||
if (CheckTypeForLLDBPrivate(TA.getAsType().getTypePtr()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::TypeIsSBClass(QualType T) {
|
||||
QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
|
||||
const auto *CXXRDecl = UnqualifiedUnderlyingType->getAsCXXRecordDecl();
|
||||
if (!CXXRDecl)
|
||||
return false; // SB Classes are always C++ classes
|
||||
|
||||
return CXXRDecl->getName().starts_with("SB");
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::TypeIsConstCharPtr(QualType T) {
|
||||
if (!T->isPointerType())
|
||||
return false;
|
||||
|
||||
QualType UnderlyingType = T->getPointeeType();
|
||||
if (!UnderlyingType.isConstQualified())
|
||||
return false;
|
||||
|
||||
// NOTE: We should be able to do `UnderlyingType->isCharType` but that will
|
||||
// return true for `const uint8_t *` since that is effectively an unsigned
|
||||
// char pointer. We currently do not support pointers other than `const char
|
||||
// *` and `const char **`.
|
||||
return UnderlyingType->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
||||
UnderlyingType->isSpecificBuiltinType(BuiltinType::SChar);
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::TypeIsConstCharPtrPtr(QualType T) {
|
||||
if (!T->isPointerType())
|
||||
return false;
|
||||
|
||||
return TypeIsConstCharPtr(T->getPointeeType());
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::TypeIsDisallowedClass(QualType T) {
|
||||
QualType UUT = GetUnqualifiedUnderlyingType(T);
|
||||
const auto *CXXRDecl = UUT->getAsCXXRecordDecl();
|
||||
if (!CXXRDecl)
|
||||
return false;
|
||||
|
||||
llvm::StringRef DeclName = CXXRDecl->getName();
|
||||
for (const llvm::StringRef DisallowedClass : DisallowedClasses)
|
||||
if (DeclName == DisallowedClass)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::TypeIsCallbackFunctionPointer(QualType T) {
|
||||
return T->isFunctionPointerType();
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::MethodIsDisallowed(ASTContext &Context,
|
||||
CXXMethodDecl *MDecl) {
|
||||
bool isDisallowed = false;
|
||||
std::string MangledName = lldb_rpc_gen::GetMangledName(Context, MDecl);
|
||||
if (llvm::is_contained(DisallowedMethods, MangledName))
|
||||
isDisallowed = true;
|
||||
|
||||
if (MDecl->hasAttrs()) {
|
||||
for (auto *attr : MDecl->getAttrs()) {
|
||||
if (strcmp(attr->getAttrName()->getNameStart(), "deprecated") == 0)
|
||||
isDisallowed = true;
|
||||
}
|
||||
}
|
||||
return isDisallowed;
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::HasCallbackParameter(CXXMethodDecl *MDecl) {
|
||||
bool HasCallbackParameter = false;
|
||||
bool HasBatonParameter = false;
|
||||
auto End = MDecl->parameters().end();
|
||||
for (auto Iter = MDecl->parameters().begin(); Iter != End; Iter++) {
|
||||
if ((*Iter)->getType()->isFunctionPointerType())
|
||||
HasCallbackParameter = true;
|
||||
else if ((*Iter)->getType()->isVoidPointerType())
|
||||
HasBatonParameter = true;
|
||||
}
|
||||
|
||||
return HasCallbackParameter && HasBatonParameter;
|
||||
}
|
||||
|
||||
// NOTE: There's possibly a more clever way to do this, but we're keeping
|
||||
// the string replacement way here. Here is why it is written this way:
|
||||
// By the time we have already created a `Method` object, we have extracted the
|
||||
// `QualifiedName` and the relevant QualTypes for parameters/return types, many
|
||||
// of which contains "lldb::" in them. To change it in a way that would be
|
||||
// friendly to liblldbrpc, we would need to have a way of replacing that
|
||||
// namespace at the time of creating a Method, and only for liblldbrpc methods.
|
||||
// IMO this would complicate Method more than what I'm doing here, and not
|
||||
// necessarily for any more benefit.
|
||||
// In clang-tools-extra, there is a ChangeNamespaces tool which tries to do
|
||||
// something similar to this. It also operates primarily on string replacement,
|
||||
// but uses more sophisticated clang tooling to do so.
|
||||
// For now, this will do what we need it to do.
|
||||
std::string
|
||||
lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(std::string Name) {
|
||||
const char *lldb_namespace = "lldb::";
|
||||
auto Pos = Name.find(lldb_namespace);
|
||||
while (Pos != std::string::npos) {
|
||||
constexpr size_t SizeOfLLDBNamespace = 6;
|
||||
Name.replace(Pos, SizeOfLLDBNamespace, "lldb_rpc::");
|
||||
Pos = Name.find(lldb_namespace);
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
std::string lldb_rpc_gen::StripLLDBNamespace(std::string Name) {
|
||||
const char *lldb_namespace = "lldb::";
|
||||
auto Pos = Name.find(lldb_namespace);
|
||||
if (Pos != std::string::npos) {
|
||||
constexpr size_t SizeOfLLDBNamespace = 6;
|
||||
Name = Name.substr(Pos + SizeOfLLDBNamespace);
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::SBClassRequiresDefaultCtor(const std::string &ClassName) {
|
||||
return !llvm::is_contained(ClassesWithoutDefaultCtor, ClassName);
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::SBClassRequiresCopyCtorAssign(const std::string &ClassName) {
|
||||
return !llvm::is_contained(ClassesWithoutCopyOperations, ClassName);
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::SBClassInheritsFromObjectRef(const std::string &ClassName) {
|
||||
return llvm::is_contained(ClassesThatInheritFromObjectRef, ClassName);
|
||||
}
|
||||
|
||||
std::string lldb_rpc_gen::GetSBClassNameFromType(QualType T) {
|
||||
assert(lldb_rpc_gen::TypeIsSBClass(T) &&
|
||||
"Cannot get SBClass name from non-SB class type!");
|
||||
|
||||
QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
|
||||
const auto *CXXRDecl = UnqualifiedUnderlyingType->getAsCXXRecordDecl();
|
||||
assert(CXXRDecl && "SB class was not CXXRecordDecl!");
|
||||
if (!CXXRDecl)
|
||||
return std::string();
|
||||
|
||||
return CXXRDecl->getName().str();
|
||||
}
|
||||
lldb_rpc_gen::Method::Method(CXXMethodDecl *MDecl, const PrintingPolicy &Policy,
|
||||
ASTContext &Context)
|
||||
: Policy(Policy), Context(Context),
|
||||
QualifiedName(MDecl->getQualifiedNameAsString()),
|
||||
BaseName(MDecl->getNameAsString()),
|
||||
MangledName(lldb_rpc_gen::GetMangledName(Context, MDecl)),
|
||||
ReturnType(MDecl->getReturnType()), IsConst(MDecl->isConst()),
|
||||
IsInstance(MDecl->isInstance()), IsCtor(isa<CXXConstructorDecl>(MDecl)),
|
||||
IsCopyAssign(MDecl->isCopyAssignmentOperator()),
|
||||
IsMoveAssign(MDecl->isMoveAssignmentOperator()),
|
||||
IsDtor(isa<CXXDestructorDecl>(MDecl)),
|
||||
IsConversionMethod(isa<CXXConversionDecl>(MDecl)) {
|
||||
uint8_t UnnamedArgIdx = 0;
|
||||
bool PrevParamWasPointer = false;
|
||||
for (const auto *ParamDecl : MDecl->parameters()) {
|
||||
Param param;
|
||||
if (ParamDecl->hasDefaultArg())
|
||||
param.DefaultValueText =
|
||||
Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(
|
||||
ParamDecl->getDefaultArg()->getSourceRange()),
|
||||
Context.getSourceManager(), Context.getLangOpts())
|
||||
.str();
|
||||
|
||||
param.IsFollowedByLen = false;
|
||||
param.Name = ParamDecl->getNameAsString();
|
||||
// If the parameter has no name, we'll generate one
|
||||
if (param.Name.empty()) {
|
||||
param.Name = "arg" + std::to_string(UnnamedArgIdx);
|
||||
UnnamedArgIdx++;
|
||||
}
|
||||
param.Type = ParamDecl->getType();
|
||||
|
||||
// FIXME: Instead of using this heuristic, the ideal thing would be to add
|
||||
// annotations to the SBAPI methods themselves. For now, we have a list of
|
||||
// methods that we know will need this.
|
||||
if (PrevParamWasPointer) {
|
||||
PrevParamWasPointer = false;
|
||||
const bool IsIntegerType = param.Type->isIntegerType() &&
|
||||
!param.Type->isBooleanType() &&
|
||||
!param.Type->isEnumeralType();
|
||||
if (IsIntegerType && llvm::is_contained(MethodsWithPointerPlusLen,
|
||||
llvm::StringRef(MangledName)))
|
||||
Params.back().IsFollowedByLen = true;
|
||||
}
|
||||
|
||||
if (param.Type->isPointerType() &&
|
||||
!lldb_rpc_gen::TypeIsConstCharPtr(param.Type) &&
|
||||
!param.Type->isFunctionPointerType())
|
||||
PrevParamWasPointer = true;
|
||||
|
||||
if (param.Type->isFunctionPointerType())
|
||||
ContainsFunctionPointerParameter = true;
|
||||
|
||||
Params.push_back(param);
|
||||
}
|
||||
|
||||
if (IsInstance)
|
||||
ThisType = MDecl->getThisType();
|
||||
|
||||
if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(MDecl)) {
|
||||
IsExplicitCtorOrConversionMethod = CtorDecl->isExplicit();
|
||||
IsCopyCtor = CtorDecl->isCopyConstructor();
|
||||
IsMoveCtor = CtorDecl->isMoveConstructor();
|
||||
} else if (const auto *ConversionDecl = dyn_cast<CXXConversionDecl>(MDecl))
|
||||
IsExplicitCtorOrConversionMethod = ConversionDecl->isExplicit();
|
||||
}
|
||||
|
||||
// Adding a '<' allows us to use Methods in ordered containers.
|
||||
// The ordering is on memory addresses.
|
||||
bool lldb_rpc_gen::Method::operator<(const lldb_rpc_gen::Method &rhs) const {
|
||||
return this < &rhs;
|
||||
}
|
||||
|
||||
std::string
|
||||
lldb_rpc_gen::Method::CreateParamListAsString(GenerationKind Generation,
|
||||
bool IncludeDefaultValue) const {
|
||||
assert((!IncludeDefaultValue || Generation == eLibrary) &&
|
||||
"Default values should only be emitted on the library side!");
|
||||
|
||||
std::vector<std::string> ParamList;
|
||||
|
||||
if (Generation == eLibrary && RequiresConnectionParameter())
|
||||
ParamList.push_back("const rpc::Connection &connection");
|
||||
|
||||
for (const auto &Param : Params) {
|
||||
std::string ParamString;
|
||||
llvm::raw_string_ostream ParamStringStream(ParamString);
|
||||
|
||||
if (Generation == eLibrary)
|
||||
ParamStringStream << lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
|
||||
Param.Type.getAsString(Policy));
|
||||
else
|
||||
ParamStringStream << Param.Type.getAsString(Policy);
|
||||
|
||||
ParamStringStream << " " << Param.Name;
|
||||
if (IncludeDefaultValue && Generation == eLibrary &&
|
||||
!Param.DefaultValueText.empty())
|
||||
ParamStringStream << " = "
|
||||
<< lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
|
||||
Param.DefaultValueText);
|
||||
|
||||
ParamList.push_back(ParamString);
|
||||
}
|
||||
|
||||
return llvm::join(ParamList, ", ");
|
||||
}
|
||||
|
||||
bool lldb_rpc_gen::Method::RequiresConnectionParameter() const {
|
||||
if (!IsCtor && IsInstance)
|
||||
return false;
|
||||
if (IsCopyCtor || IsMoveCtor)
|
||||
return false;
|
||||
for (const auto &Param : Params)
|
||||
// We can re-use the connection from our parameter if possible.
|
||||
// Const-qualified parameters are input parameters and already
|
||||
// have a valid connection to provide to the current method.
|
||||
if (TypeIsSBClass(Param.Type) &&
|
||||
GetUnderlyingType(Param.Type).isConstQualified())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
//===-- RPCCommon.h -------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_RPC_GEN_RPCCOMMON_H
|
||||
#define LLDB_RPC_GEN_RPCCOMMON_H
|
||||
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace lldb_rpc_gen {
|
||||
QualType GetUnderlyingType(QualType T);
|
||||
QualType GetUnqualifiedUnderlyingType(QualType T);
|
||||
std::string GetMangledName(ASTContext &Context, CXXMethodDecl *MDecl);
|
||||
|
||||
bool TypeIsFromLLDBPrivate(QualType T);
|
||||
bool TypeIsSBClass(QualType T);
|
||||
bool TypeIsConstCharPtr(QualType T);
|
||||
bool TypeIsConstCharPtrPtr(QualType T);
|
||||
bool TypeIsDisallowedClass(QualType T);
|
||||
bool TypeIsCallbackFunctionPointer(QualType T);
|
||||
|
||||
bool MethodIsDisallowed(ASTContext &Context, CXXMethodDecl *MDecl);
|
||||
bool HasCallbackParameter(CXXMethodDecl *MDecl);
|
||||
|
||||
std::string ReplaceLLDBNamespaceWithRPCNamespace(std::string Name);
|
||||
std::string StripLLDBNamespace(std::string Name);
|
||||
bool SBClassRequiresDefaultCtor(const std::string &ClassName);
|
||||
bool SBClassRequiresCopyCtorAssign(const std::string &ClassName);
|
||||
bool SBClassInheritsFromObjectRef(const std::string &ClassName);
|
||||
std::string GetSBClassNameFromType(QualType T);
|
||||
struct Param {
|
||||
std::string Name;
|
||||
QualType Type;
|
||||
std::string DefaultValueText;
|
||||
bool IsFollowedByLen;
|
||||
};
|
||||
|
||||
enum GenerationKind : bool { eServer, eLibrary };
|
||||
|
||||
struct Method {
|
||||
enum Type { eOther, eConstructor, eDestructor };
|
||||
|
||||
Method(CXXMethodDecl *MDecl, const PrintingPolicy &Policy,
|
||||
ASTContext &Context);
|
||||
|
||||
// Adding a '<' allows us to use Methods in ordered containers.
|
||||
// The ordering is on memory addresses.
|
||||
bool operator<(const lldb_rpc_gen::Method &rhs) const;
|
||||
const PrintingPolicy &Policy;
|
||||
const ASTContext &Context;
|
||||
std::string QualifiedName;
|
||||
std::string BaseName;
|
||||
std::string MangledName;
|
||||
QualType ReturnType;
|
||||
QualType ThisType;
|
||||
std::vector<Param> Params;
|
||||
bool IsConst = false;
|
||||
bool IsInstance = false;
|
||||
bool IsCtor = false;
|
||||
bool IsCopyCtor = false;
|
||||
bool IsCopyAssign = false;
|
||||
bool IsMoveCtor = false;
|
||||
bool IsMoveAssign = false;
|
||||
bool IsDtor = false;
|
||||
bool IsConversionMethod = false;
|
||||
bool IsExplicitCtorOrConversionMethod = false;
|
||||
bool ContainsFunctionPointerParameter = false;
|
||||
|
||||
std::string CreateParamListAsString(GenerationKind Generation,
|
||||
bool IncludeDefaultValue = false) const;
|
||||
|
||||
bool RequiresConnectionParameter() const;
|
||||
};
|
||||
|
||||
std::string
|
||||
GetDefaultArgumentsForConstructor(std::string ClassName,
|
||||
const lldb_rpc_gen::Method &method);
|
||||
|
||||
class FileEmitter {
|
||||
protected:
|
||||
FileEmitter(std::unique_ptr<llvm::ToolOutputFile> &&OutputFile)
|
||||
: OutputFile(std::move(OutputFile)), IndentLevel(0) {}
|
||||
void EmitLine(const std::string &line) {
|
||||
for (auto i = 0; i < IndentLevel; i++)
|
||||
OutputFile->os() << " ";
|
||||
|
||||
OutputFile->os() << line << "\n";
|
||||
}
|
||||
|
||||
void EmitNewLine() { OutputFile->os() << "\n"; }
|
||||
|
||||
std::unique_ptr<llvm::ToolOutputFile> OutputFile;
|
||||
uint8_t IndentLevel;
|
||||
};
|
||||
} // namespace lldb_rpc_gen
|
||||
#endif // LLDB_RPC_GEN_RPCCOMMON_H
|
@ -7,8 +7,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RPCCommon.h"
|
||||
#include "server/RPCServerHeaderEmitter.h"
|
||||
#include "server/RPCServerSourceEmitter.h"
|
||||
#include "RPCServerHeaderEmitter.h"
|
||||
#include "RPCServerSourceEmitter.h"
|
||||
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
@ -40,15 +40,15 @@ static llvm::cl::opt<std::string>
|
||||
llvm::cl::desc("Directory to output generated files to"),
|
||||
llvm::cl::init(""), llvm::cl::cat(RPCGenCategory));
|
||||
|
||||
static std::string GetServerOutputDirectory() {
|
||||
static std::string GetLibraryOutputDirectory() {
|
||||
llvm::SmallString<128> Path(OutputDir.getValue());
|
||||
llvm::sys::path::append(Path, "server");
|
||||
llvm::sys::path::append(Path, "lib");
|
||||
return std::string(Path);
|
||||
}
|
||||
|
||||
static std::unique_ptr<llvm::ToolOutputFile>
|
||||
CreateOutputFile(llvm::StringRef OutputDir, llvm::StringRef Filename) {
|
||||
llvm::SmallString<256> Path(OutputDir);
|
||||
llvm::SmallString<128> Path(OutputDir);
|
||||
llvm::sys::path::append(Path, Filename);
|
||||
|
||||
std::error_code EC;
|
||||
@ -100,8 +100,7 @@ public:
|
||||
for (CXXMethodDecl *MDecl : RDecl->methods()) {
|
||||
const std::string MangledName =
|
||||
lldb_rpc_gen::GetMangledName(Context, MDecl);
|
||||
const bool IsDisallowed =
|
||||
lldb_rpc_gen::MethodIsDisallowed(Context, MDecl);
|
||||
const bool IsDisallowed = lldb_rpc_gen::MethodIsDisallowed(MangledName);
|
||||
const bool HasCallbackParameter =
|
||||
lldb_rpc_gen::HasCallbackParameter(MDecl);
|
||||
SupportLevel MethodSupportLevel = GetMethodSupportLevel(MDecl);
|
||||
@ -315,9 +314,9 @@ bool EmitClassNamesFile(std::set<std::string> &ClassNames) {
|
||||
if (!ClassNamesFile)
|
||||
return false;
|
||||
|
||||
ClassNamesFile->os() << "#ifndef SBCLASS\n"
|
||||
<< "#error \"SBClass must be defined\"\n"
|
||||
<< "#endif\n";
|
||||
ClassNamesFile->os() << "#ifndef SBCLASS\n";
|
||||
ClassNamesFile->os() << "#error \"SBClass must be defined\"\n";
|
||||
ClassNamesFile->os() << "#endif\n";
|
||||
|
||||
for (const auto &ClassName : ClassNames) {
|
||||
if (ClassName == "SBStream" || ClassName == "SBProgress")
|
||||
@ -341,9 +340,9 @@ bool EmitMethodNamesFile(std::set<std::string> &MangledMethodNames) {
|
||||
if (!MethodNamesFile)
|
||||
return false;
|
||||
|
||||
MethodNamesFile->os() << "#ifndef GENERATE_SBAPI\n"
|
||||
<< "#error \"GENERATE_SBAPI must be defined\"\n"
|
||||
<< "#endif\n";
|
||||
MethodNamesFile->os() << "#ifndef GENERATE_SBAPI\n";
|
||||
MethodNamesFile->os() << "#error \"GENERATE_SBAPI must be defined\"\n";
|
||||
MethodNamesFile->os() << "#endif\n";
|
||||
|
||||
for (const auto &MangledName : MangledMethodNames) {
|
||||
MethodNamesFile->os() << "GENERATE_SBAPI(" << MangledName << ")\n";
|
||||
@ -359,8 +358,9 @@ bool EmitSkippedMethodsFile(std::set<std::string> &SkippedMethodNames) {
|
||||
if (!File)
|
||||
return false;
|
||||
|
||||
for (const auto &Skipped : SkippedMethodNames)
|
||||
for (const auto &Skipped : SkippedMethodNames) {
|
||||
File->os() << Skipped << "\n";
|
||||
}
|
||||
File->keep();
|
||||
return true;
|
||||
}
|
||||
@ -381,14 +381,6 @@ int main(int argc, const char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the output directory if the user specified one does not exist.
|
||||
if (!llvm::sys::fs::exists(OutputDir.getValue())) {
|
||||
llvm::sys::fs::create_directory(OutputDir.getValue());
|
||||
}
|
||||
|
||||
if (!llvm::sys::fs::exists(GetServerOutputDirectory())) {
|
||||
llvm::sys::fs::create_directory(GetServerOutputDirectory());
|
||||
}
|
||||
CommonOptionsParser &OP = ExpectedParser.get();
|
||||
auto PCHOpts = std::make_shared<PCHContainerOperations>();
|
||||
PCHOpts->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
|
||||
|
Loading…
x
Reference in New Issue
Block a user