Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,2 @@
add_subdirectory(Clang)
add_subdirectory(Go)

View File

@ -0,0 +1,109 @@
//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ASTDumper.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/raw_ostream.h"
using namespace lldb_private;
ASTDumper::ASTDumper(clang::Decl *decl) {
clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl);
bool has_external_lexical_storage;
bool has_external_visible_storage;
if (decl_ctx) {
has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
decl_ctx->setHasExternalLexicalStorage(false);
decl_ctx->setHasExternalVisibleStorage(false);
}
llvm::raw_string_ostream os(m_dump);
decl->print(os);
os.flush();
if (decl_ctx) {
decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
}
}
ASTDumper::ASTDumper(clang::DeclContext *decl_ctx) {
bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
decl_ctx->setHasExternalLexicalStorage(false);
decl_ctx->setHasExternalVisibleStorage(false);
if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) {
llvm::raw_string_ostream os(m_dump);
decl->print(os);
os.flush();
} else {
m_dump.assign("<DeclContext is not a Decl>");
}
decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
}
ASTDumper::ASTDumper(const clang::Type *type) {
m_dump = clang::QualType(type, 0).getAsString();
}
ASTDumper::ASTDumper(clang::QualType type) { m_dump = type.getAsString(); }
ASTDumper::ASTDumper(lldb::opaque_compiler_type_t type) {
m_dump = clang::QualType::getFromOpaquePtr(type).getAsString();
}
ASTDumper::ASTDumper(const CompilerType &compiler_type) {
m_dump = ClangUtil::GetQualType(compiler_type).getAsString();
}
const char *ASTDumper::GetCString() { return m_dump.c_str(); }
void ASTDumper::ToSTDERR() { fprintf(stderr, "%s\n", m_dump.c_str()); }
void ASTDumper::ToLog(Log *log, const char *prefix) {
size_t len = m_dump.length() + 1;
char *alloc = (char *)malloc(len);
char *str = alloc;
memcpy(str, m_dump.c_str(), len);
char *end = NULL;
end = strchr(str, '\n');
while (end) {
*end = '\0';
log->Printf("%s%s", prefix, str);
*end = '\n';
str = end + 1;
end = strchr(str, '\n');
}
log->Printf("%s%s", prefix, str);
free(alloc);
}
void ASTDumper::ToStream(lldb::StreamSP &stream) { stream->PutCString(m_dump); }

View File

@ -0,0 +1,41 @@
//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ASTDumper_h_
#define liblldb_ASTDumper_h_
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/DenseSet.h"
namespace lldb_private {
class ASTDumper {
public:
ASTDumper(clang::Decl *decl);
ASTDumper(clang::DeclContext *decl_ctx);
ASTDumper(const clang::Type *type);
ASTDumper(clang::QualType type);
ASTDumper(lldb::opaque_compiler_type_t type);
ASTDumper(const CompilerType &compiler_type);
const char *GetCString();
void ToSTDERR();
void ToLog(Log *log, const char *prefix);
void ToStream(lldb::StreamSP &stream);
private:
std::string m_dump;
};
} // namespace lldb_private
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
//===-- ASTResultSynthesizer.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ASTResultSynthesizer_h_
#define liblldb_ASTResultSynthesizer_h_
#include "lldb/Core/ClangForward.h"
#include "lldb/Target/Target.h"
#include "clang/Sema/SemaConsumer.h"
namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTResultSynthesizer ASTResultSynthesizer.h
/// "lldb/Expression/ASTResultSynthesizer.h"
/// @brief Adds a result variable declaration to the ASTs for an expression.
///
/// Users expect the expression "i + 3" to return a result, even if a result
/// variable wasn't specifically declared. To fulfil this requirement, LLDB
/// adds
/// a result variable to the expression, transforming it to
/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the
/// resulting variable is mapped to the right piece of memory.
/// ASTResultSynthesizer's job is to add the variable and its initialization to
/// the ASTs for the expression, and it does so by acting as a SemaConsumer for
/// Clang.
//----------------------------------------------------------------------
class ASTResultSynthesizer : public clang::SemaConsumer {
public:
//----------------------------------------------------------------------
/// Constructor
///
/// @param[in] passthrough
/// Since the ASTs must typically go through to the Clang code generator
/// in order to produce LLVM IR, this SemaConsumer must allow them to
/// pass to the next step in the chain after processing. Passthrough is
/// the next ASTConsumer, or NULL if none is required.
///
/// @param[in] top_level
/// If true, register all top-level Decls and don't try to handle the
/// main function.
///
/// @param[in] target
/// The target, which contains the persistent variable store and the
/// AST importer.
//----------------------------------------------------------------------
ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level,
Target &target);
//----------------------------------------------------------------------
/// Destructor
//----------------------------------------------------------------------
~ASTResultSynthesizer() override;
//----------------------------------------------------------------------
/// Link this consumer with a particular AST context
///
/// @param[in] Context
/// This AST context will be used for types and identifiers, and also
/// forwarded to the passthrough consumer, if one exists.
//----------------------------------------------------------------------
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
/// Examine a list of Decls to find the function $__lldb_expr and
/// transform its code
///
/// @param[in] D
/// The list of Decls to search. These may contain LinkageSpecDecls,
/// which need to be searched recursively. That job falls to
/// TransformTopLevelDecl.
//----------------------------------------------------------------------
bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleTranslationUnit(clang::ASTContext &Ctx) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleTagDeclDefinition(clang::TagDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void CompleteTentativeDefinition(clang::VarDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleVTable(clang::CXXRecordDecl *RD) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void PrintStats() override;
//----------------------------------------------------------------------
/// Set the Sema object to use when performing transforms, and pass it on
///
/// @param[in] S
/// The Sema to use. Because Sema isn't externally visible, this class
/// casts it to an Action for actual use.
//----------------------------------------------------------------------
void InitializeSema(clang::Sema &S) override;
//----------------------------------------------------------------------
/// Reset the Sema to NULL now that transformations are done
//----------------------------------------------------------------------
void ForgetSema() override;
//----------------------------------------------------------------------
/// The parse has succeeded, so record its persistent decls
//----------------------------------------------------------------------
void CommitPersistentDecls();
private:
//----------------------------------------------------------------------
/// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing
/// as necessary through LinkageSpecDecls, and calling SynthesizeResult on
/// anything that was found
///
/// @param[in] D
/// The Decl to hunt.
//----------------------------------------------------------------------
void TransformTopLevelDecl(clang::Decl *D);
//----------------------------------------------------------------------
/// Process an Objective-C method and produce the result variable and
/// initialization
///
/// @param[in] MethodDecl
/// The method to process.
//----------------------------------------------------------------------
bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl);
//----------------------------------------------------------------------
/// Process a function and produce the result variable and initialization
///
/// @param[in] FunDecl
/// The function to process.
//----------------------------------------------------------------------
bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl);
//----------------------------------------------------------------------
/// Process a function body and produce the result variable and
/// initialization
///
/// @param[in] Body
/// The body of the function.
///
/// @param[in] DC
/// The DeclContext of the function, into which the result variable
/// is inserted.
//----------------------------------------------------------------------
bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC);
//----------------------------------------------------------------------
/// Given a DeclContext for a function or method, find all types
/// declared in the context and record any persistent types found.
///
/// @param[in] FunDeclCtx
/// The context for the function to process.
//----------------------------------------------------------------------
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx);
//----------------------------------------------------------------------
/// Given a TypeDecl, if it declares a type whose name starts with a
/// dollar sign, register it as a pointer type in the target's scratch
/// AST context.
///
/// @param[in] Body
/// The body of the function.
//----------------------------------------------------------------------
void MaybeRecordPersistentType(clang::TypeDecl *D);
//----------------------------------------------------------------------
/// Given a NamedDecl, register it as a pointer type in the target's scratch
/// AST context.
///
/// @param[in] Body
/// The body of the function.
//----------------------------------------------------------------------
void RecordPersistentDecl(clang::NamedDecl *D);
clang::ASTContext
*m_ast_context; ///< The AST context to use for identifiers and types.
clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for
///passthrough. NULL if it's a
///SemaConsumer.
clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain,
///for passthrough. NULL if it's an
///ASTConsumer.
std::vector<clang::NamedDecl *> m_decls; ///< Persistent declarations to
///register assuming the expression
///succeeds.
Target &m_target; ///< The target, which contains the persistent variable
///store and the
clang::Sema *m_sema; ///< The Sema to use.
bool m_top_level;
};
} // namespace lldb_private
#endif // liblldb_ASTResultSynthesizer_h_

View File

@ -0,0 +1,186 @@
//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ASTStructExtractor.h"
#include "lldb/Utility/Log.h"
#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace clang;
using namespace lldb_private;
ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
const char *struct_name,
ClangFunctionCaller &function)
: m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL),
m_sema(NULL), m_action(NULL), m_function(function),
m_struct_name(struct_name) {
if (!m_passthrough)
return;
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
ASTStructExtractor::~ASTStructExtractor() {}
void ASTStructExtractor::Initialize(ASTContext &Context) {
m_ast_context = &Context;
if (m_passthrough)
m_passthrough->Initialize(Context);
}
void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) {
if (!F->hasBody())
return;
Stmt *body_stmt = F->getBody();
CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt);
if (!body_compound_stmt)
return; // do we have to handle this?
RecordDecl *struct_decl = NULL;
StringRef desired_name(m_struct_name);
for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(),
be = body_compound_stmt->body_end();
bi != be; ++bi) {
Stmt *curr_stmt = *bi;
DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt);
if (!curr_decl_stmt)
continue;
DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup();
for (Decl *candidate_decl : decl_group) {
RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl);
if (!candidate_record_decl)
continue;
if (candidate_record_decl->getName() == desired_name) {
struct_decl = candidate_record_decl;
break;
}
}
if (struct_decl)
break;
}
if (!struct_decl)
return;
const ASTRecordLayout *struct_layout(
&m_ast_context->getASTRecordLayout(struct_decl));
if (!struct_layout)
return;
m_function.m_struct_size =
struct_layout->getSize()
.getQuantity(); // TODO Store m_struct_size as CharUnits
m_function.m_return_offset =
struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
m_function.m_return_size =
struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
field_index < num_fields; ++field_index) {
m_function.m_member_offsets.push_back(
struct_layout->getFieldOffset(field_index) / 8);
}
m_function.m_struct_valid = true;
}
void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) {
LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
if (linkage_spec_decl) {
RecordDecl::decl_iterator decl_iterator;
for (decl_iterator = linkage_spec_decl->decls_begin();
decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) {
ExtractFromTopLevelDecl(*decl_iterator);
}
}
FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
if (m_ast_context && function_decl &&
!m_function.m_wrapper_function_name.compare(
function_decl->getNameAsString())) {
ExtractFromFunctionDecl(function_decl);
}
}
bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) {
DeclGroupRef::iterator decl_iterator;
for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) {
Decl *decl = *decl_iterator;
ExtractFromTopLevelDecl(decl);
}
if (m_passthrough)
return m_passthrough->HandleTopLevelDecl(D);
return true;
}
void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) {
if (m_passthrough)
m_passthrough->HandleTranslationUnit(Ctx);
}
void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) {
if (m_passthrough)
m_passthrough->HandleTagDeclDefinition(D);
}
void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) {
if (m_passthrough)
m_passthrough->CompleteTentativeDefinition(D);
}
void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) {
if (m_passthrough)
m_passthrough->HandleVTable(RD);
}
void ASTStructExtractor::PrintStats() {
if (m_passthrough)
m_passthrough->PrintStats();
}
void ASTStructExtractor::InitializeSema(Sema &S) {
m_sema = &S;
m_action = reinterpret_cast<Action *>(m_sema);
if (m_passthrough_sema)
m_passthrough_sema->InitializeSema(S);
}
void ASTStructExtractor::ForgetSema() {
m_sema = NULL;
m_action = NULL;
if (m_passthrough_sema)
m_passthrough_sema->ForgetSema();
}

View File

@ -0,0 +1,164 @@
//===-- ASTStructExtractor.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ASTStructExtractor_h_
#define liblldb_ASTStructExtractor_h_
#include "ClangExpressionVariable.h"
#include "ClangFunctionCaller.h"
#include "lldb/Core/ClangForward.h"
#include "clang/Sema/SemaConsumer.h"
namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTStructExtractor ASTStructExtractor.h
/// "lldb/Expression/ASTStructExtractor.h"
/// @brief Extracts and describes the argument structure for a wrapped function.
///
/// This pass integrates with ClangFunctionCaller, which calls functions with
/// custom
/// sets of arguments. To avoid having to implement the full calling convention
/// for the target's architecture, ClangFunctionCaller writes a simple wrapper
/// function that takes a pointer to an argument structure that contains room
/// for the address of the function to be called, the values of all its
/// arguments, and room for the function's return value.
///
/// The definition of this struct is itself in the body of the wrapper function,
/// so Clang does the structure layout itself. ASTStructExtractor reads through
/// the AST for the wrapper function and finds the struct.
//----------------------------------------------------------------------
class ASTStructExtractor : public clang::SemaConsumer {
public:
//----------------------------------------------------------------------
/// Constructor
///
/// @param[in] passthrough
/// Since the ASTs must typically go through to the Clang code generator
/// in order to produce LLVM IR, this SemaConsumer must allow them to
/// pass to the next step in the chain after processing. Passthrough is
/// the next ASTConsumer, or NULL if none is required.
///
/// @param[in] struct_name
/// The name of the structure to extract from the wrapper function.
///
/// @param[in] function
/// The caller object whose members should be populated with information
/// about the argument struct. ClangFunctionCaller friends
/// ASTStructExtractor
/// for this purpose.
//----------------------------------------------------------------------
ASTStructExtractor(clang::ASTConsumer *passthrough, const char *struct_name,
ClangFunctionCaller &function);
//----------------------------------------------------------------------
/// Destructor
//----------------------------------------------------------------------
~ASTStructExtractor() override;
//----------------------------------------------------------------------
/// Link this consumer with a particular AST context
///
/// @param[in] Context
/// This AST context will be used for types and identifiers, and also
/// forwarded to the passthrough consumer, if one exists.
//----------------------------------------------------------------------
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
/// Examine a list of Decls to find the function $__lldb_expr and
/// transform its code
///
/// @param[in] D
/// The list of Decls to search. These may contain LinkageSpecDecls,
/// which need to be searched recursively. That job falls to
/// TransformTopLevelDecl.
//----------------------------------------------------------------------
bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleTranslationUnit(clang::ASTContext &Ctx) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleTagDeclDefinition(clang::TagDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void CompleteTentativeDefinition(clang::VarDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void HandleVTable(clang::CXXRecordDecl *RD) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
void PrintStats() override;
//----------------------------------------------------------------------
/// Set the Sema object to use when performing transforms, and pass it on
///
/// @param[in] S
/// The Sema to use. Because Sema isn't externally visible, this class
/// casts it to an Action for actual use.
//----------------------------------------------------------------------
void InitializeSema(clang::Sema &S) override;
//----------------------------------------------------------------------
/// Reset the Sema to NULL now that transformations are done
//----------------------------------------------------------------------
void ForgetSema() override;
private:
//----------------------------------------------------------------------
/// Hunt the given FunctionDecl for the argument struct and place
/// information about it into m_function
///
/// @param[in] F
/// The FunctionDecl to hunt.
//----------------------------------------------------------------------
void ExtractFromFunctionDecl(clang::FunctionDecl *F);
//----------------------------------------------------------------------
/// Hunt the given Decl for FunctionDecls named the same as the wrapper
/// function name, recursing as necessary through LinkageSpecDecls, and
/// calling ExtractFromFunctionDecl on anything that was found
///
/// @param[in] D
/// The Decl to hunt.
//----------------------------------------------------------------------
void ExtractFromTopLevelDecl(clang::Decl *D);
clang::ASTContext
*m_ast_context; ///< The AST context to use for identifiers and types.
clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for
///passthrough. NULL if it's a
///SemaConsumer.
clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain,
///for passthrough. NULL if it's an
///ASTConsumer.
clang::Sema *m_sema; ///< The Sema to use.
clang::Action
*m_action; ///< The Sema to use, cast to an Action so it's usable.
ClangFunctionCaller &m_function; ///< The function to populate with
///information about the argument structure.
std::string m_struct_name; ///< The name of the structure to extract.
};
} // namespace lldb_private
#endif // liblldb_ASTStructExtractor_h_

View File

@ -0,0 +1,48 @@
if(NOT LLDB_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
add_lldb_library(lldbPluginExpressionParserClang PLUGIN
ASTDumper.cpp
ASTResultSynthesizer.cpp
ASTStructExtractor.cpp
ClangASTSource.cpp
ClangExpressionDeclMap.cpp
ClangExpressionParser.cpp
ClangExpressionVariable.cpp
ClangFunctionCaller.cpp
ClangModulesDeclVendor.cpp
ClangPersistentVariables.cpp
ClangUserExpression.cpp
ClangUtilityFunction.cpp
IRForTarget.cpp
DEPENDS
${tablegen_deps}
LINK_LIBS
clangAST
clangCodeGen
clangEdit
clangFrontend
clangLex
clangParse
clangRewrite
clangRewriteFrontend
clangSema
clangSerialization
lldbCore
lldbExpression
lldbHost
lldbInterpreter
lldbSymbol
lldbTarget
lldbUtility
lldbPluginCPlusPlusLanguage
LINK_COMPONENTS
Core
ExecutionEngine
ipo
MCJIT
Support
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
//===-- ClangDiagnostic.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_ClangDiagnostic_h
#define lldb_ClangDiagnostic_h
#include <vector>
#include "clang/Basic/Diagnostic.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
#include "lldb/Expression/DiagnosticManager.h"
namespace lldb_private {
class ClangDiagnostic : public Diagnostic {
public:
typedef std::vector<clang::FixItHint> FixItList;
static inline bool classof(const ClangDiagnostic *) { return true; }
static inline bool classof(const Diagnostic *diag) {
return diag->getKind() == eDiagnosticOriginClang;
}
ClangDiagnostic(const char *message, DiagnosticSeverity severity,
uint32_t compiler_id)
: Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) {}
virtual ~ClangDiagnostic() = default;
bool HasFixIts() const override { return !m_fixit_vec.empty(); }
void AddFixitHint(const clang::FixItHint &fixit) {
m_fixit_vec.push_back(fixit);
}
const FixItList &FixIts() const { return m_fixit_vec; }
FixItList m_fixit_vec;
};
} // namespace lldb_private
#endif /* lldb_ClangDiagnostic_h */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
//===-- ClangExpressionHelper.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ClangExpression_h_
#define liblldb_ClangExpression_h_
// C Includes
// C++ Includes
#include <map>
#include <string>
#include <vector>
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Expression/ExpressionTypeSystemHelper.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class RecordingMemoryManager;
//----------------------------------------------------------------------
// ClangExpressionHelper
//----------------------------------------------------------------------
class ClangExpressionHelper : public ExpressionTypeSystemHelper {
public:
static bool classof(const ExpressionTypeSystemHelper *ts) {
return ts->getKind() == eKindClangHelper;
}
ClangExpressionHelper()
: ExpressionTypeSystemHelper(
ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) {}
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
virtual ~ClangExpressionHelper() {}
//------------------------------------------------------------------
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
//------------------------------------------------------------------
virtual ClangExpressionDeclMap *DeclMap() = 0;
//------------------------------------------------------------------
/// Return the object that the parser should allow to access ASTs.
/// May be NULL if the ASTs do not need to be transformed.
///
/// @param[in] passthrough
/// The ASTConsumer that the returned transformer should send
/// the ASTs to after transformation.
//------------------------------------------------------------------
virtual clang::ASTConsumer *
ASTTransformer(clang::ASTConsumer *passthrough) = 0;
virtual void CommitPersistentDecls() {}
protected:
};
} // namespace lldb_private
#endif // liblldb_ClangExpression_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
//===-- ClangExpressionParser.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ClangExpressionParser_h_
#define liblldb_ClangExpressionParser_h_
#include "lldb/Core/ClangForward.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionParser.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-public.h"
#include <string>
#include <vector>
namespace lldb_private {
class IRExecutionUnit;
//----------------------------------------------------------------------
/// @class ClangExpressionParser ClangExpressionParser.h
/// "lldb/Expression/ClangExpressionParser.h"
/// @brief Encapsulates an instance of Clang that can parse expressions.
///
/// ClangExpressionParser is responsible for preparing an instance of
/// ClangExpression for execution. ClangExpressionParser uses ClangExpression
/// as a glorified parameter list, performing the required parsing and
/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
/// that can be executed.
//----------------------------------------------------------------------
class ClangExpressionParser : public ExpressionParser {
public:
//------------------------------------------------------------------
/// Constructor
///
/// Initializes class variables.
///
/// @param[in] exe_scope,
/// If non-NULL, an execution context scope that can help to
/// correctly create an expression with a valid process for
/// optional tuning Objective-C runtime support. Can be NULL.
///
/// @param[in] expr
/// The expression to be parsed.
//------------------------------------------------------------------
ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr,
bool generate_debug_info);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
~ClangExpressionParser() override;
//------------------------------------------------------------------
/// Parse a single expression and convert it to IR using Clang. Don't
/// wrap the expression in anything at all.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager to report errors to.
///
/// @return
/// The number of errors encountered during parsing. 0 means
/// success.
//------------------------------------------------------------------
unsigned Parse(DiagnosticManager &diagnostic_manager) override;
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override;
//------------------------------------------------------------------
/// Ready an already-parsed expression for execution, possibly
/// evaluating it statically.
///
/// @param[out] func_addr
/// The address to which the function has been written.
///
/// @param[out] func_end
/// The end of the function's allocated memory region. (func_addr
/// and func_end do not delimit an allocated region; the allocated
/// region may begin before func_addr.)
///
/// @param[in] execution_unit_sp
/// After parsing, ownership of the execution unit for
/// for the expression is handed to this shared pointer.
///
/// @param[in] exe_ctx
/// The execution context to write the function into.
///
/// @param[out] evaluated_statically
/// Set to true if the expression could be interpreted statically;
/// untouched otherwise.
///
/// @param[out] const_result
/// If the result of the expression is constant, and the
/// expression has no side effects, this is set to the result of the
/// expression.
///
/// @param[in] execution_policy
/// Determines whether the expression must be JIT-compiled, must be
/// evaluated statically, or whether this decision may be made
/// opportunistically.
///
/// @return
/// An error code indicating the success or failure of the operation.
/// Test with Success().
//------------------------------------------------------------------
Status
PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end,
lldb::IRExecutionUnitSP &execution_unit_sp,
ExecutionContext &exe_ctx, bool &can_interpret,
lldb_private::ExecutionPolicy execution_policy) override;
//------------------------------------------------------------------
/// Run all static initializers for an execution unit.
///
/// @param[in] execution_unit_sp
/// The execution unit.
///
/// @param[in] exe_ctx
/// The execution context to use when running them. Thread can't be null.
///
/// @return
/// The error code indicating the
//------------------------------------------------------------------
Status RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp,
ExecutionContext &exe_ctx);
//------------------------------------------------------------------
/// Returns a string representing current ABI.
///
/// @param[in] target_arch
/// The target architecture.
///
/// @return
/// A string representing target ABI for the current architecture.
//-------------------------------------------------------------------
std::string GetClangTargetABI(const ArchSpec &target_arch);
private:
std::unique_ptr<llvm::LLVMContext>
m_llvm_context; ///< The LLVM context to generate IR into
std::unique_ptr<clang::FileManager>
m_file_manager; ///< The Clang file manager object used by the compiler
std::unique_ptr<clang::CompilerInstance>
m_compiler; ///< The Clang compiler used to parse expressions into IR
std::unique_ptr<clang::Builtin::Context>
m_builtin_context; ///< Context for Clang built-ins
std::unique_ptr<clang::SelectorTable>
m_selector_table; ///< Selector table for Objective-C methods
std::unique_ptr<clang::CodeGenerator>
m_code_generator; ///< The Clang object that generates IR
class LLDBPreprocessorCallbacks;
LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor
///encounters module imports
std::unique_ptr<ClangASTContext> m_ast_context;
};
}
#endif // liblldb_ClangExpressionParser_h_

View File

@ -0,0 +1,67 @@
//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ClangExpressionVariable.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Stream.h"
#include "clang/AST/ASTContext.h"
using namespace lldb_private;
using namespace clang;
ClangExpressionVariable::ClangExpressionVariable(
ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order,
uint32_t addr_byte_size)
: ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(),
m_jit_vars() {
m_flags = EVNone;
m_frozen_sp =
ValueObjectConstResult::Create(exe_scope, byte_order, addr_byte_size);
}
ClangExpressionVariable::ClangExpressionVariable(
ExecutionContextScope *exe_scope, Value &value, const ConstString &name,
uint16_t flags)
: ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(),
m_jit_vars() {
m_flags = flags;
m_frozen_sp = ValueObjectConstResult::Create(exe_scope, value, name);
}
ClangExpressionVariable::ClangExpressionVariable(
const lldb::ValueObjectSP &valobj_sp)
: ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(),
m_jit_vars() {
m_flags = EVNone;
m_frozen_sp = valobj_sp;
}
ClangExpressionVariable::ClangExpressionVariable(
ExecutionContextScope *exe_scope, const ConstString &name,
const TypeFromUser &user_type, lldb::ByteOrder byte_order,
uint32_t addr_byte_size)
: ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(),
m_jit_vars() {
m_flags = EVNone;
m_frozen_sp =
ValueObjectConstResult::Create(exe_scope, byte_order, addr_byte_size);
SetName(name);
SetCompilerType(user_type);
}
TypeFromUser ClangExpressionVariable::GetTypeFromUser() {
TypeFromUser tfu(m_frozen_sp->GetCompilerType());
return tfu;
}

View File

@ -0,0 +1,240 @@
//===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ClangExpressionVariable_h_
#define liblldb_ClangExpressionVariable_h_
// C Includes
#include <signal.h>
#include <stdint.h>
#include <string.h>
// C++ Includes
#include <map>
#include <string>
#include <vector>
// Other libraries and framework includes
#include "llvm/Support/Casting.h"
// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-public.h"
namespace llvm {
class Value;
}
namespace lldb_private {
class ValueObjectConstResult;
//----------------------------------------------------------------------
/// @class ClangExpressionVariable ClangExpressionVariable.h
/// "lldb/Expression/ClangExpressionVariable.h"
/// @brief Encapsulates one variable for the expression parser.
///
/// The expression parser uses variables in three different contexts:
///
/// First, it stores persistent variables along with the process for use
/// in expressions. These persistent variables contain their own data
/// and are typed.
///
/// Second, in an interpreted expression, it stores the local variables
/// for the expression along with the expression. These variables
/// contain their own data and are typed.
///
/// Third, in a JIT-compiled expression, it stores the variables that
/// the expression needs to have materialized and dematerialized at each
/// execution. These do not contain their own data but are named and
/// typed.
///
/// This class supports all of these use cases using simple type
/// polymorphism, and provides necessary support methods. Its interface
/// is RTTI-neutral.
//----------------------------------------------------------------------
class ClangExpressionVariable : public ExpressionVariable {
public:
ClangExpressionVariable(ExecutionContextScope *exe_scope,
lldb::ByteOrder byte_order, uint32_t addr_byte_size);
ClangExpressionVariable(ExecutionContextScope *exe_scope, Value &value,
const ConstString &name, uint16_t flags = EVNone);
ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
ClangExpressionVariable(ExecutionContextScope *exe_scope,
const ConstString &name,
const TypeFromUser &user_type,
lldb::ByteOrder byte_order, uint32_t addr_byte_size);
//----------------------------------------------------------------------
/// Utility functions for dealing with ExpressionVariableLists in
/// Clang-specific ways
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/// Finds a variable by NamedDecl in the list.
///
/// @param[in] name
/// The name of the requested variable.
///
/// @return
/// The variable requested, or NULL if that variable is not in the list.
//----------------------------------------------------------------------
static ClangExpressionVariable *
FindVariableInList(ExpressionVariableList &list, const clang::NamedDecl *decl,
uint64_t parser_id) {
lldb::ExpressionVariableSP var_sp;
for (size_t index = 0, size = list.GetSize(); index < size; ++index) {
var_sp = list.GetVariableAtIndex(index);
if (ClangExpressionVariable *clang_var =
llvm::dyn_cast<ClangExpressionVariable>(var_sp.get())) {
ClangExpressionVariable::ParserVars *parser_vars =
clang_var->GetParserVars(parser_id);
if (parser_vars && parser_vars->m_named_decl == decl)
return clang_var;
}
}
return nullptr;
}
//----------------------------------------------------------------------
/// If the variable contains its own data, make a Value point at it.
/// If \a exe_ctx in not NULL, the value will be resolved in with
/// that execution context.
///
/// @param[in] value
/// The value to point at the data.
///
/// @param[in] exe_ctx
/// The execution context to use to resolve \a value.
///
/// @return
/// True on success; false otherwise (in particular, if this variable
/// does not contain its own data).
//----------------------------------------------------------------------
bool PointValueAtData(Value &value, ExecutionContext *exe_ctx);
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
//----------------------------------------------------------------------
class ParserVars {
public:
ParserVars()
: m_parser_type(), m_named_decl(NULL), m_llvm_value(NULL),
m_lldb_value(), m_lldb_var(), m_lldb_sym(NULL) {}
TypeFromParser
m_parser_type; ///< The type of the variable according to the parser
const clang::NamedDecl
*m_named_decl; ///< The Decl corresponding to this variable
llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable;
///usually a GlobalValue
lldb_private::Value
m_lldb_value; ///< The value found in LLDB for this variable
lldb::VariableSP m_lldb_var; ///< The original variable for this variable
const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this
///variable, if it was a symbol
};
private:
typedef std::map<uint64_t, ParserVars> ParserVarMap;
ParserVarMap m_parser_vars;
public:
//----------------------------------------------------------------------
/// Make this variable usable by the parser by allocating space for
/// parser-specific variables
//----------------------------------------------------------------------
void EnableParserVars(uint64_t parser_id) {
m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
}
//----------------------------------------------------------------------
/// Deallocate parser-specific variables
//----------------------------------------------------------------------
void DisableParserVars(uint64_t parser_id) { m_parser_vars.erase(parser_id); }
//----------------------------------------------------------------------
/// Access parser-specific variables
//----------------------------------------------------------------------
ParserVars *GetParserVars(uint64_t parser_id) {
ParserVarMap::iterator i = m_parser_vars.find(parser_id);
if (i == m_parser_vars.end())
return NULL;
else
return &i->second;
}
//----------------------------------------------------------------------
/// The following values are valid if the variable is used by JIT code
//----------------------------------------------------------------------
struct JITVars {
JITVars() : m_alignment(0), m_size(0), m_offset(0) {}
lldb::offset_t
m_alignment; ///< The required alignment of the variable, in bytes
size_t m_size; ///< The space required for the variable, in bytes
lldb::offset_t
m_offset; ///< The offset of the variable in the struct, in bytes
};
private:
typedef std::map<uint64_t, JITVars> JITVarMap;
JITVarMap m_jit_vars;
public:
//----------------------------------------------------------------------
/// Make this variable usable for materializing for the JIT by allocating
/// space for JIT-specific variables
//----------------------------------------------------------------------
void EnableJITVars(uint64_t parser_id) {
m_jit_vars.insert(std::make_pair(parser_id, JITVars()));
}
//----------------------------------------------------------------------
/// Deallocate JIT-specific variables
//----------------------------------------------------------------------
void DisableJITVars(uint64_t parser_id) { m_jit_vars.erase(parser_id); }
JITVars *GetJITVars(uint64_t parser_id) {
JITVarMap::iterator i = m_jit_vars.find(parser_id);
if (i == m_jit_vars.end())
return NULL;
else
return &i->second;
}
TypeFromUser GetTypeFromUser();
//------------------------------------------------------------------
// llvm casting support
//------------------------------------------------------------------
static bool classof(const ExpressionVariable *ev) {
return ev->getKind() == ExpressionVariable::eKindClang;
}
//----------------------------------------------------------------------
/// Members
//----------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN(ClangExpressionVariable);
};
} // namespace lldb_private
#endif // liblldb_ClangExpressionVariable_h_

View File

@ -0,0 +1,226 @@
//===-- ClangFunctionCaller.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ClangFunctionCaller.h"
#include "ASTStructExtractor.h"
#include "ClangExpressionParser.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/Module.h"
// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
using namespace lldb_private;
//----------------------------------------------------------------------
// ClangFunctionCaller constructor
//----------------------------------------------------------------------
ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
const CompilerType &return_type,
const Address &functionAddress,
const ValueList &arg_value_list,
const char *name)
: FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list,
name),
m_type_system_helper(*this) {
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
// Can't make a ClangFunctionCaller without a process.
assert(m_jit_process_wp.lock());
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ClangFunctionCaller::~ClangFunctionCaller() {}
unsigned
ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
DiagnosticManager &diagnostic_manager) {
if (m_compiled)
return 0;
// Compilation might call code, make sure to keep on the thread the caller
// indicated.
ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
thread_to_use_sp);
// FIXME: How does clang tell us there's no return value? We need to handle
// that case.
unsigned num_errors = 0;
std::string return_type_str(
m_function_return_type.GetTypeName().AsCString(""));
// Cons up the function we're going to wrap our call in, then compile it...
// We declare the function "extern "C"" because the compiler might be in C++
// mode which would mangle the name and then we couldn't find it again...
m_wrapper_function_text.clear();
m_wrapper_function_text.append("extern \"C\" void ");
m_wrapper_function_text.append(m_wrapper_function_name);
m_wrapper_function_text.append(" (void *input)\n{\n struct ");
m_wrapper_function_text.append(m_wrapper_struct_name);
m_wrapper_function_text.append(" \n {\n");
m_wrapper_function_text.append(" ");
m_wrapper_function_text.append(return_type_str);
m_wrapper_function_text.append(" (*fn_ptr) (");
// Get the number of arguments. If we have a function type and it is
// prototyped,
// trust that, otherwise use the values we were given.
// FIXME: This will need to be extended to handle Variadic functions. We'll
// need
// to pull the defined arguments out of the function, then add the types from
// the
// arguments list for the variable arguments.
uint32_t num_args = UINT32_MAX;
bool trust_function = false;
// GetArgumentCount returns -1 for an unprototyped function.
CompilerType function_clang_type;
if (m_function_ptr) {
function_clang_type = m_function_ptr->GetCompilerType();
if (function_clang_type) {
int num_func_args = function_clang_type.GetFunctionArgumentCount();
if (num_func_args >= 0) {
trust_function = true;
num_args = num_func_args;
}
}
}
if (num_args == UINT32_MAX)
num_args = m_arg_values.GetSize();
std::string args_buffer; // This one stores the definition of all the args in
// "struct caller".
std::string args_list_buffer; // This one stores the argument list called from
// the structure.
for (size_t i = 0; i < num_args; i++) {
std::string type_name;
if (trust_function) {
type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i)
.GetTypeName()
.AsCString("");
} else {
CompilerType clang_qual_type =
m_arg_values.GetValueAtIndex(i)->GetCompilerType();
if (clang_qual_type) {
type_name = clang_qual_type.GetTypeName().AsCString("");
} else {
diagnostic_manager.Printf(
eDiagnosticSeverityError,
"Could not determine type of input value %" PRIu64 ".",
(uint64_t)i);
return 1;
}
}
m_wrapper_function_text.append(type_name);
if (i < num_args - 1)
m_wrapper_function_text.append(", ");
char arg_buf[32];
args_buffer.append(" ");
args_buffer.append(type_name);
snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
args_buffer.push_back(' ');
args_buffer.append(arg_buf);
args_buffer.append(";\n");
args_list_buffer.append("__lldb_fn_data->");
args_list_buffer.append(arg_buf);
if (i < num_args - 1)
args_list_buffer.append(", ");
}
m_wrapper_function_text.append(
");\n"); // Close off the function calling prototype.
m_wrapper_function_text.append(args_buffer);
m_wrapper_function_text.append(" ");
m_wrapper_function_text.append(return_type_str);
m_wrapper_function_text.append(" return_value;");
m_wrapper_function_text.append("\n };\n struct ");
m_wrapper_function_text.append(m_wrapper_struct_name);
m_wrapper_function_text.append("* __lldb_fn_data = (struct ");
m_wrapper_function_text.append(m_wrapper_struct_name);
m_wrapper_function_text.append(" *) input;\n");
m_wrapper_function_text.append(
" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
m_wrapper_function_text.append(args_list_buffer);
m_wrapper_function_text.append(");\n}\n");
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
// Okay, now compile this expression
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
if (jit_process_sp) {
const bool generate_debug_info = true;
m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this,
generate_debug_info));
num_errors = m_parser->Parse(diagnostic_manager);
} else {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"no process - unable to inject function");
num_errors = 1;
}
m_compiled = (num_errors == 0);
if (!m_compiled)
return num_errors;
return num_errors;
}
clang::ASTConsumer *
ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer(
clang::ASTConsumer *passthrough) {
m_struct_extractor.reset(new ASTStructExtractor(
passthrough, m_owner.GetWrapperStructName(), m_owner));
return m_struct_extractor.get();
}

View File

@ -0,0 +1,165 @@
//===-- ClangFunctionCaller.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ClangFunctionCaller_h_
#define liblldb_ClangFunctionCaller_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "ClangExpressionHelper.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Process.h"
namespace lldb_private {
class ASTStructExtractor;
class ClangExpressionParser;
//----------------------------------------------------------------------
/// @class ClangFunctionCaller ClangFunctionCaller.h
/// "lldb/Expression/ClangFunctionCaller.h"
/// @brief Encapsulates a function that can be called.
///
/// A given ClangFunctionCaller object can handle a single function signature.
/// Once constructed, it can set up any number of concurrent calls to
/// functions with that signature.
///
/// It performs the call by synthesizing a structure that contains the pointer
/// to the function and the arguments that should be passed to that function,
/// and producing a special-purpose JIT-compiled function that accepts a void*
/// pointing to this struct as its only argument and calls the function in the
/// struct with the written arguments. This method lets Clang handle the
/// vagaries of function calling conventions.
///
/// The simplest use of the ClangFunctionCaller is to construct it with a
/// function representative of the signature you want to use, then call
/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
///
/// If you need to reuse the arguments for several calls, you can call
/// InsertFunction() followed by WriteFunctionArguments(), which will return
/// the location of the args struct for the wrapper function in args_addr_ref.
///
/// If you need to call the function on the thread plan stack, you can also
/// call InsertFunction() followed by GetThreadPlanToCallFunction().
///
/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
/// and its address returned in that variable.
///
/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
/// argument space will be managed for you.
//----------------------------------------------------------------------
class ClangFunctionCaller : public FunctionCaller {
friend class ASTStructExtractor;
class ClangFunctionCallerHelper : public ClangExpressionHelper {
public:
ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {}
~ClangFunctionCallerHelper() override = default;
//------------------------------------------------------------------
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
//------------------------------------------------------------------
ClangExpressionDeclMap *DeclMap() override { return NULL; }
//------------------------------------------------------------------
/// Return the object that the parser should allow to access ASTs.
/// May be NULL if the ASTs do not need to be transformed.
///
/// @param[in] passthrough
/// The ASTConsumer that the returned transformer should send
/// the ASTs to after transformation.
//------------------------------------------------------------------
clang::ASTConsumer *
ASTTransformer(clang::ASTConsumer *passthrough) override;
private:
ClangFunctionCaller &m_owner;
std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that
///generates the
///argument struct
///layout.
};
public:
//------------------------------------------------------------------
/// Constructor
///
/// @param[in] exe_scope
/// An execution context scope that gets us at least a target and
/// process.
///
/// @param[in] ast_context
/// The AST context to evaluate argument types in.
///
/// @param[in] return_qualtype
/// An opaque Clang QualType for the function result. Should be
/// defined in ast_context.
///
/// @param[in] function_address
/// The address of the function to call.
///
/// @param[in] arg_value_list
/// The default values to use when calling this function. Can
/// be overridden using WriteFunctionArguments().
//------------------------------------------------------------------
ClangFunctionCaller(ExecutionContextScope &exe_scope,
const CompilerType &return_type,
const Address &function_address,
const ValueList &arg_value_list, const char *name);
~ClangFunctionCaller() override;
//------------------------------------------------------------------
/// Compile the wrapper function
///
/// @param[in] thread_to_use_sp
/// Compilation might end up calling functions. Pass in the thread you
/// want the compilation to use. If you pass in an empty ThreadSP it will
/// use the currently selected thread.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager to report parser errors to.
///
/// @return
/// The number of errors.
//------------------------------------------------------------------
unsigned CompileFunction(lldb::ThreadSP thread_to_use_sp,
DiagnosticManager &diagnostic_manager) override;
ExpressionTypeSystemHelper *GetTypeSystemHelper() override {
return &m_type_system_helper;
}
protected:
const char *GetWrapperStructName() { return m_wrapper_struct_name.c_str(); }
private:
//------------------------------------------------------------------
// For ClangFunctionCaller only
//------------------------------------------------------------------
// Note: the parser needs to be destructed before the execution unit, so
// declare the execution unit first.
ClangFunctionCallerHelper m_type_system_helper;
};
} // namespace lldb_private
#endif // liblldb_ClangFunctionCaller_h_

Some files were not shown because too many files have changed in this diff Show More