diff options
Diffstat (limited to 'lldb/source')
39 files changed, 3312 insertions, 69 deletions
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index ee467402569..5862b9570b0 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -21,7 +21,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/Block.h" diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 5ee5e1e0588..c38cb2b595c 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -23,7 +23,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 7ca9ebf08d5..93454b13bdc 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -35,7 +35,7 @@ #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/Endian.h" diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index 4b689da027b..5382da6a5ab 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,15 +1,4 @@ add_lldb_library(lldbExpression - ASTDumper.cpp - ASTResultSynthesizer.cpp - ASTStructExtractor.cpp - ClangASTSource.cpp - ClangExpressionDeclMap.cpp - ClangExpressionParser.cpp - ClangFunctionCaller.cpp - ClangModulesDeclVendor.cpp - ClangPersistentVariables.cpp - ClangUserExpression.cpp - ClangUtilityFunction.cpp DWARFExpression.cpp Expression.cpp ExpressionSourceCode.cpp @@ -17,7 +6,6 @@ add_lldb_library(lldbExpression FunctionCaller.cpp IRDynamicChecks.cpp IRExecutionUnit.cpp - IRForTarget.cpp IRInterpreter.cpp IRMemoryMap.cpp Materializer.cpp diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 1d0ad6f7bf3..ebcc2846039 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -24,7 +24,7 @@ #include "lldb/Core/Value.h" #include "lldb/Core/VMRange.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Host/Endian.h" diff --git a/lldb/source/Expression/ExpressionSourceCode.cpp b/lldb/source/Expression/ExpressionSourceCode.cpp index 9a42510d0a2..4c0370389f3 100644 --- a/lldb/source/Expression/ExpressionSourceCode.cpp +++ b/lldb/source/Expression/ExpressionSourceCode.cpp @@ -10,8 +10,8 @@ #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Symbol/Block.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp index d52eb5b1378..ddc378dcb41 100644 --- a/lldb/source/Expression/FunctionCaller.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/ASTStructExtractor.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 450d1adc939..84e04bd3f35 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -12,7 +12,7 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectVariable.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Expression/Materializer.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" @@ -1016,7 +1016,7 @@ private: }; uint32_t -Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err) +Materializer::AddResultVariable (const CompilerType &type, bool is_program_reference, bool keep_in_memory, Error &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory)); diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index a2984363a06..1537e031d37 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -22,13 +22,12 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Expression/ASTResultSynthesizer.h" -#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" #include "lldb/Expression/UserExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" diff --git a/lldb/source/Expression/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index c63e4cc2862..976310610f5 100644 --- a/lldb/source/Expression/ASTDumper.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "ASTDumper.h" + #include "lldb/Core/Log.h" -#include "lldb/Expression/ASTDumper.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompilerType.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h new file mode 100644 index 00000000000..c8dc6847d6c --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h @@ -0,0 +1,42 @@ +//===-- 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/Core/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 diff --git a/lldb/source/Expression/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index c3d42cb49ec..5bba7a9c2bc 100644 --- a/lldb/source/Expression/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "ASTResultSynthesizer.h" + +#include "ClangPersistentVariables.h" + #include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -20,8 +24,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include "lldb/Core/Log.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ASTResultSynthesizer.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Target/Target.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h new file mode 100644 index 00000000000..b8063a380ca --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -0,0 +1,185 @@ +//===-- 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 "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/TaggedASTType.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] target + /// The target, which contains the persistent variable store and the + /// AST importer. + //---------------------------------------------------------------------- + ASTResultSynthesizer(clang::ASTConsumer *passthrough, + 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; + +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); + + 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. + Target &m_target; ///< The target, which contains the persistent variable store and the + clang::Sema *m_sema; ///< The Sema to use. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTResultSynthesizer_h_ diff --git a/lldb/source/Expression/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp index 049173e32f3..38a2b6b33a8 100644 --- a/lldb/source/Expression/ASTStructExtractor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "ASTStructExtractor.h" + #include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -20,7 +22,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include "lldb/Core/Log.h" -#include "lldb/Expression/ASTStructExtractor.h" using namespace llvm; using namespace clang; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h new file mode 100644 index 00000000000..2152cff911f --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -0,0 +1,158 @@ +//===-- 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 "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.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_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt index ed8930a06b6..e18dde6b700 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt @@ -1,3 +1,15 @@ add_lldb_library(lldbPluginExpressionParserClang + 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 ) diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index a3d380c2125..82ffdf16040 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -7,15 +7,16 @@ // //===----------------------------------------------------------------------===// +#include "ClangASTSource.h" + +#include "ASTDumper.h" +#include "ClangModulesDeclVendor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Function.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h new file mode 100644 index 00000000000..9f4d238cacd --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -0,0 +1,526 @@ +//===-- ClangASTSource.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_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include <set> + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types. Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource : + public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource (const lldb::TargetSP &target) : + m_import_in_progress (false), + m_lookups_enabled (false), + m_target (target), + m_ast_context (NULL), + m_active_lexical_decls (), + m_active_lookups () + { + m_ast_importer = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource() override; + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } + clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } + uint32_t GetNumExternalSelectors () override { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override + { return NULL; } + void MaterializeVisibleDecls (const clang::DeclContext *DC) + { return; } + + void InstallASTContext (clang::ASTContext *ast_context) + { + m_ast_context = ast_context; + m_ast_importer->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// A callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + void FindExternalLexicalDecls( + const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override; + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override; + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::TagDecl *Tag) override; + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace (NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls (NameSearchContext &context); + + void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } + bool GetImportInProgress () { return m_import_in_progress; } + + void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } + bool GetLookupsEnabled () { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon + { + public: + ClangASTSourceProxy (ClangASTSource &original) : + m_original(original) + { + } + + bool + FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override + { + return m_original.FindExternalVisibleDeclsByName(DC, Name); + } + + void + FindExternalLexicalDecls(const clang::DeclContext *DC, + llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override + { + return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); + } + + void + CompleteType(clang::TagDecl *Tag) override + { + return m_original.CompleteType(Tag); + } + + void + CompleteType(clang::ObjCInterfaceDecl *Class) override + { + return m_original.CompleteType(Class); + } + + bool + layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } + + void + StartTranslationUnit(clang::ASTConsumer *Consumer) override + { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata * + GetMetadata(const void * object) + { + return m_original.GetMetadata(object); + } + + void + SetMetadata(const void * object, ClangASTMetadata &metadata) + { + return m_original.SetMetadata(object, metadata); + } + + bool + HasMetadata(const void * object) + { + return m_original.HasMetadata(object); + } + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() + { + return new ClangASTSourceProxy(*this); + } + +protected: + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCMethodDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCPropertyAndIvarDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] src_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + CompilerType + GuardedCopyType (const CompilerType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP m_target; ///< The target to use in finding variables and types. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + ClangASTImporter *m_ast_importer; ///< The target's AST importer. + std::set<const clang::Decl *> m_active_lexical_decls; + std::set<const char *> m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +/// +/// LLDB needs to create Decls for entities it finds. This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet <CompilerType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext (ClangASTSource &astSource, + llvm::SmallVectorImpl<clang::NamedDecl*> &decls, + clang::DeclarationName &name, + const clang::DeclContext *dc) : + m_ast_source(astSource), + m_decls(decls), + m_decl_name(name), + m_decl_context(dc) + { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const CompilerType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const CompilerType &type, + bool extern_c = false); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] compiler_type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); + + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult (clang::DeclContextLookupResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl (clang::NamedDecl *decl); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTSource_h_ diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 5bf939e8375..533f7c268c7 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -7,7 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Expression/ClangExpressionDeclMap.h" +#include "ClangExpressionDeclMap.h" + +#include "ASTDumper.h" +#include "ClangASTSource.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" @@ -21,10 +27,6 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/Materializer.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h new file mode 100644 index 00000000000..1ed2c4e3f20 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -0,0 +1,705 @@ +//===-- ClangExpressionDeclMap.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_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> + +// C++ Includes +#include <vector> + +#include "ClangExpressionVariable.h" +#include "ClangASTSource.h" + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression. The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name. But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap : + public ClangASTSource +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap (bool keep_result_in_memory, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap() override; + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool + WillParse (ExecutionContext &exe_ctx, + Materializer *materializer); + + void + InstallCodeGenerator (clang::ASTConsumer *code_gen); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void + DidParse (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddPersistentVariable (const clang::NamedDecl *decl, + const ConstString &name, + TypeFromParser type, + bool is_result, + bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddValueToStruct (const clang::NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + lldb::offset_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + DoStructLayout (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructInfo (uint32_t &num_elements, + size_t &size, + lldb::offset_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructElement (const clang::NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionInfo (const clang::NamedDecl *decl, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a function given nothing + /// but its name. Some functions are needed but didn't get Decls made + /// during parsing -- specifically, sel_registerName is never called + /// in the generated IR but we need to call it nonetheless. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the address could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionAddress (const ConstString &name, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t + GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + Module *module = NULL); + + lldb::addr_t + GetSymbolAddress (const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo + { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : + byte_order(lldb::eByteOrderInvalid), + address_byte_size(0) + { + } + + bool IsValid() + { + return (byte_order != lldb::eByteOrderInvalid && + address_byte_size != 0); + } + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls(NameSearchContext &context) override; + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] name + /// The name as a plain C string. The NameSearchContext contains + /// a DeclarationName for the name so at first the name may seem + /// redundant, but ClangExpressionDeclMap operates in RTTI land so + /// it can't access DeclarationName. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); +private: + ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. + ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : + m_decl_map(decl_map) + { + } + + Target * + GetTarget() + { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; + } + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. + bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. + clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN (ParserVars); + }; + + std::unique_ptr<ParserVars> m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars() + { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars() + { + m_parser_vars.reset(); + } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() : + m_struct_alignment(0), + m_struct_size(0), + m_struct_laid_out(false), + m_result_name(), + m_object_pointer_type(NULL, NULL) + { + } + + lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). + ConstString m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists + }; + + std::unique_ptr<StructVars> m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void + EnableStructVars() + { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void + DisableStructVars() + { + m_struct_vars.reset(); + } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t + GetParserID() + { + return (uint64_t)this; + } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //------------------------------------------------------------------ + const Symbol * + FindGlobalDataSymbol (Target &target, + const ConstString &name, + Module *module = NULL); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP + FindGlobalVariable (Target &target, + lldb::ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool + GetVariableValue (lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::VariableSP var, + lldb::ValueObjectSP valobj, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::ExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void + AddOneGenericVariable (NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void + AddOneFunction (NameSearchContext &context, + Function *fun, + Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void + AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void + AddOneType (NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Copy a C++ class type into the parser's AST context and add a + /// member function declaration to it for the expression. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + + TypeFromParser + CopyClassType(TypeFromUser &type, + unsigned int current_id); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 432ddbb5505..8b679a9edc9 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -7,7 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Expression/ClangExpressionParser.h" +#include "ClangExpressionParser.h" + +#include "ClangASTSource.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionDeclMap.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBufferHeap.h" @@ -18,11 +24,6 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpressionHelper.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRInterpreter.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h new file mode 100644 index 00000000000..01ab3d8f2d2 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -0,0 +1,138 @@ +//===-- 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/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/ExpressionParser.h" + +#include "IRForTarget.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] stream + /// The stream to print errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + unsigned + Parse (Stream &stream) 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(). + //------------------------------------------------------------------ + Error + PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + std::shared_ptr<IRExecutionUnit> &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; + +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_ diff --git a/lldb/source/Expression/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index 628952fe6b8..0d0d7475a00 100644 --- a/lldb/source/Expression/ClangFunctionCaller.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "ClangFunctionCaller.h" + +#include "ASTStructExtractor.h" +#include "ClangExpressionParser.h" // C Includes // C++ Includes @@ -28,9 +32,6 @@ #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/ASTStructExtractor.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/ClangASTContext.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h new file mode 100644 index 00000000000..7922f14edd8 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -0,0 +1,175 @@ +//===-- 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 +#include <vector> +#include <list> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/ClangExpressionHelper.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() {} + + //------------------------------------------------------------------ + /// 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); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangFunctionCaller() override; + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] errors + /// The stream to print parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + unsigned + CompileFunction (Stream &errors) 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_ diff --git a/lldb/source/Expression/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index e8253630724..65ee3e0ff5c 100644 --- a/lldb/source/Expression/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -9,7 +9,7 @@ #include <mutex> // std::once -#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "ClangModulesDeclVendor.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h new file mode 100644 index 00000000000..df3b20550f9 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -0,0 +1,128 @@ +//===-- ClangModulesDeclVendor.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_ClangModulesDeclVendor_h +#define liblldb_ClangModulesDeclVendor_h + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" +#include "lldb/Target/Platform.h" + +#include <set> +#include <vector> + +namespace lldb_private +{ + +class ClangModulesDeclVendor : public DeclVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangModulesDeclVendor(); + + ~ClangModulesDeclVendor() override; + + static ClangModulesDeclVendor * + Create(Target &target); + + typedef std::vector<ConstString> ModulePath; + typedef uintptr_t ModuleID; + typedef std::vector<ModuleID> ModuleVector; + + //------------------------------------------------------------------ + /// Add a module to the list of modules to search. + /// + /// @param[in] path + /// The path to the exact module to be loaded. E.g., if the desired + /// module is std.io, then this should be { "std", "io" }. + /// + /// @param[in] exported_modules + /// If non-NULL, a pointer to a vector to populate with the ID of every + /// module that is re-exported by the specified module. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the module. + /// + /// @return + /// True if the module could be loaded; false if not. If the + /// compiler encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Add all modules referred to in a given compilation unit to the list + /// of modules to search. + /// + /// @param[in] cu + /// The compilation unit to scan for imported modules. + /// + /// @param[in] exported_modules + /// A vector to populate with the ID of each module loaded (directly + /// and via re-exports) in this way. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the modules. + /// + /// @return + /// True if all modules referred to by the compilation unit could be + /// loaded; false if one could not be loaded. If the compiler + /// encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Enumerate all the macros that are defined by a given set of modules + /// that are already imported. + /// + /// @param[in] modules + /// The unique IDs for all modules to query. Later modules have higher + /// priority, just as if you @imported them in that order. This matters + /// if module A #defines a macro and module B #undefs it. + /// + /// @param[in] handler + /// A function to call with the text of each #define (including the + /// #define directive). #undef directives are not included; we simply + /// elide any corresponding #define. If this function returns true, + /// we stop the iteration immediately. + //------------------------------------------------------------------ + virtual void + ForEachMacro(const ModuleVector &modules, + std::function<bool (const std::string &)> handler) = 0; + + //------------------------------------------------------------------ + /// Query whether Clang supports modules for a particular language. + /// LLDB uses this to decide whether to try to find the modules loaded + /// by a gaiven compile unit. + /// + /// @param[in] language + /// The language to query for. + /// + /// @return + /// True if Clang has modules for the given language. + //------------------------------------------------------------------ + static bool + LanguageSupportsClangModules (lldb::LanguageType language); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangModulesDeclVendor_h diff --git a/lldb/source/Expression/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 13859b81ac8..beaa1d69da3 100644 --- a/lldb/source/Expression/ClangPersistentVariables.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Expression/ClangPersistentVariables.h" +#include "ClangPersistentVariables.h" + #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h new file mode 100644 index 00000000000..828badb9564 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -0,0 +1,91 @@ +//===-- ClangPersistentVariables.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_ClangPersistentVariables_h_ +#define liblldb_ClangPersistentVariables_h_ + +#include "ClangExpressionVariable.h" +#include "ClangModulesDeclVendor.h" + +#include "llvm/ADT/DenseMap.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between expression invocations. +/// +/// A list of variables that can be accessed and updated by any expression. See +/// ClangPersistentVariable for more discussion. Also provides an increasing, +/// 0-based counter for naming result variables. +//---------------------------------------------------------------------- +class ClangPersistentVariables : public ExpressionVariableList +{ +public: + + //---------------------------------------------------------------------- + /// Constructor + //---------------------------------------------------------------------- + ClangPersistentVariables (); + + lldb::ExpressionVariableSP + CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp); + + ClangExpressionVariable * + CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size); + + //---------------------------------------------------------------------- + /// Return the next entry in the sequence of strings "$0", "$1", ... for + /// use naming persistent expression convenience variables. + /// + /// @return + /// A string that contains the next persistent variable name. + //---------------------------------------------------------------------- + ConstString + GetNextPersistentVariableName (); + + void + RemovePersistentVariable (lldb::ExpressionVariableSP variable); + + void + RegisterPersistentType (const ConstString &name, + clang::TypeDecl *tag_decl); + + clang::TypeDecl * + GetPersistentType (const ConstString &name); + + void + AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) + { + m_hand_loaded_clang_modules.push_back(module); + } + + const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() + { + return m_hand_loaded_clang_modules; + } + +private: + uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). + + typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap; + PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. + + ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- + ///< priority source for macros. +}; + +} + +#endif diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index a6e5923bf28..3d86c521738 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -16,18 +16,20 @@ #include <string> #include <map> +#include "ClangUserExpression.h" + +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Expression/ASTResultSynthesizer.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ClangUserExpression.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h new file mode 100644 index 00000000000..a2b8beda0ac --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -0,0 +1,204 @@ +//===-- ClangUserExpression.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_ClangUserExpression_h_ +#define liblldb_ClangUserExpression_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "ASTStructExtractor.h" +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionVariable.h" +#include "IRForTarget.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUserExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangUserExpression : public UserExpression +{ +public: + + enum { kDefaultTimeout = 500000u }; + + + class ClangUserExpressionHelper : public ClangExpressionHelper + { + public: + ClangUserExpressionHelper (Target &target) : + m_target(target) + { + } + + ~ClangUserExpressionHelper() {} + + //------------------------------------------------------------------ + /// 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 m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// 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: + Target &m_target; + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; + std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class that generates the argument struct layout. + std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangUserExpression() override; + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool + Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap () + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + } + +private: + //------------------------------------------------------------------ + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. + //------------------------------------------------------------------ + + void + ScanContext (ExecutionContext &exe_ctx, + lldb_private::Error &err) override; + + bool + AddInitialArguments (ExecutionContext &exe_ctx, + std::vector<lldb::addr_t> &args, + Stream &error_stream) override; + + ClangUserExpressionHelper m_type_system_helper; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUserExpression_h_ diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 2a07a428803..457056c64a0 100644 --- a/lldb/source/Expression/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangUtilityFunction.h" + // C Includes #include <stdio.h> #if HAVE_SYS_TYPES_H @@ -20,9 +24,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangUtilityFunction.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Host/Host.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h new file mode 100644 index 00000000000..37b1ebbba12 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -0,0 +1,137 @@ +//===-- ClangUtilityFunction.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_ClangUtilityFunction_h_ +#define liblldb_ClangUtilityFunction_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ClangExpressionHelper.h" +#include "lldb/Expression/UtilityFunction.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUtilityFunction encapsulates +/// a self-contained function meant to be used from other code. Utility +/// functions can perform error-checking for ClangUserExpressions, or can +/// simply provide a way to push a function into the target for the debugger to +/// call later on. +//---------------------------------------------------------------------- +class ClangUtilityFunction : public UtilityFunction +{ +public: + class ClangUtilityFunctionHelper : public ClangExpressionHelper + { + public: + ClangUtilityFunctionHelper () + { + } + + ~ClangUtilityFunctionHelper() override {} + + //------------------------------------------------------------------ + /// 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 m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// 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 + { + return nullptr; + } + private: + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; + }; + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name); + + ~ClangUtilityFunction() override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap() + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + } + + bool + Install (Stream &error_stream, ExecutionContext &exe_ctx) override; + +private: + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUtilityFunction_h_ diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 862e6f6cfaa..862f63b2908 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -7,7 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Expression/IRForTarget.h" +#include "IRForTarget.h" + +#include "ClangExpressionDeclMap.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Constants.h" @@ -29,7 +31,6 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/Endian.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h new file mode 100644 index 00000000000..fb4abcc103d --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -0,0 +1,745 @@ +//===-- IRForTarget.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_IRForTarget_h_ +#define liblldb_IRForTarget_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/Pass.h" + +#include <map> +#include <functional> + +namespace llvm { + class BasicBlock; + class CallInst; + class Constant; + class ConstantInt; + class Function; + class GlobalValue; + class GlobalVariable; + class Instruction; + class IntegerType; + class Module; + class StoreInst; + class DataLayout; + class Type; + class Value; +} + +namespace lldb_private { + class ClangExpressionDeclMap; + class IRExecutionUnit; + class IRMemoryMap; +} + +//---------------------------------------------------------------------- +/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" +/// @brief Transforms the IR for a function to run in the target +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRForTarget makes the second possible, by applying a series of +/// transformations to the IR which make it relocatable. These +/// transformations are discussed in more detail next to their relevant +/// functions. +//---------------------------------------------------------------------- +class IRForTarget : public llvm::ModulePass +{ +public: + enum class LookupResult { + Success, + Fail, + Ignore + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals and allocating the argument + /// struct. See the documentation for ClangExpressionDeclMap. + /// + /// @param[in] resolve_vars + /// True if the external variable references (including persistent + /// variables) should be resolved. If not, only external functions + /// are resolved. + /// + /// @param[in] execution_policy + /// Determines whether an IR interpreter can be used to statically + /// evaluate the expression. + /// + /// @param[in] const_result + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. + /// + /// @param[in] execution_unit + /// The holder for raw data associated with the expression. + /// + /// @param[in] error_stream + /// If non-NULL, a stream on which errors can be printed. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + //------------------------------------------------------------------ + IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~IRForTarget() override; + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// Implementation of the llvm::ModulePass::runOnModule() function. + /// + /// @param[in] llvm_module + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + runOnModule(llvm::Module &llvm_module) override; + + //------------------------------------------------------------------ + /// Interface stub + /// + /// Implementation of the llvm::ModulePass::assignPassManager() + /// function. + //------------------------------------------------------------------ + void + assignPassManager(llvm::PMStack &pass_mgr_stack, + llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override; + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + /// + /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() + /// function. + //------------------------------------------------------------------ + llvm::PassManagerType + getPotentialPassManagerType() const override; + +private: + //------------------------------------------------------------------ + /// Ensures that the current function's linkage is set to external. + /// Otherwise the JIT may not return an address for it. + /// + /// @param[in] llvm_function + /// The function whose linkage is to be fixed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + FixFunctionLinkage (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to replace all function pointers with their + /// integer equivalents. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + HasSideEffects (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A function-level pass to check whether the function has side + /// effects. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Get the address of a function, and a location to put the complete + /// Value of the function if one is available. + /// + /// @param[in] function + /// The function to find the location of. + /// + /// @param[out] ptr + /// The location of the function in the target. + /// + /// @param[out] name + /// The resolved name of the function (matters for intrinsics). + /// + /// @param[out] value_ptr + /// A variable to put the function's completed Value* in, or NULL + /// if the Value* shouldn't be stored anywhere. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + LookupResult + GetFunctionAddress (llvm::Function *function, + uint64_t &ptr, + lldb_private::ConstString &name, + llvm::Constant **&value_ptr); + + //------------------------------------------------------------------ + /// Build a function pointer given a type and a raw pointer. + /// + /// @param[in] type + /// The type of the function pointer to be built. + /// + /// @param[in] ptr + /// The value of the pointer. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + llvm::Constant * + BuildFunctionPointer (llvm::Type *type, + uint64_t ptr); + + void + RegisterFunctionMetadata (llvm::LLVMContext &context, + llvm::Value *function_ptr, + const char *name); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True if the function has side effects (or if this cannot + /// be determined); false otherwise. + //------------------------------------------------------------------ + bool + ResolveFunctionPointers (llvm::Module &llvm_module); + + //------------------------------------------------------------------ + /// A function-level pass to take the generated global value + /// $__lldb_expr_result and make it into a persistent variable. + /// Also see ASTResultSynthesizer. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Find the NamedDecl corresponding to a Value. This interface is + /// exposed for the IR interpreter. + /// + /// @param[in] module + /// The module containing metadata to search + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ +public: + static clang::NamedDecl * + DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); +private: + clang::NamedDecl * + DeclForGlobal (llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// + /// @param[in] initializer + /// The constant initializer for the variable. + /// + /// @param[in] name + /// The name of the result variable. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetConstantResult (llvm::Constant *initializer, + const lldb_private::ConstString &name, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetCastResult (lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CreateResultVariable (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to find Objective-C constant strings and + /// transform them to calls to CFStringCreateWithBytes. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a single Objective-C constant string. + /// + /// @param[in] NSStr + /// The constant NSString to be transformed + /// + /// @param[in] CStr + /// The constant C string inside the NSString. This will be + /// passed as the bytes argument to CFStringCreateWithBytes. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstString (llvm::GlobalVariable *NSStr, + llvm::GlobalVariable *CStr); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all Objective-C method calls and + /// rewrite them to use sel_registerName instead of statically allocated + /// selectors. The reason is that the selectors are created on the + /// assumption that the Objective-C runtime will scan the appropriate + /// section and prepare them. This doesn't happen when code is copied + /// into the target, though, and there's no easy way to induce the + /// runtime to scan them. So instead we get our selectors from + /// sel_registerName. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Replace a single selector reference + /// + /// @param[in] selector_load + /// The load of the statically-allocated selector. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelector (llvm::Instruction* selector_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelectors (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all newly-declared persistent + /// variables and register them with the ClangExprDeclMap. This + /// allows them to be materialized and dematerialized like normal + /// external variables. Before transformation, these persistent + /// variables look like normal locals, so they have an allocation. + /// This pass excises these allocations and makes references look + /// like external references where they will be resolved -- like all + /// other external references -- by ResolveExternals(). + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Handle a single allocation of a persistent variable + /// + /// @param[in] persistent_alloc + /// The allocation of the persistent variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewritePersistentAlloc (llvm::Instruction *persistent_alloc); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + //------------------------------------------------------------------ + bool + RewritePersistentAllocs (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to find all external variables and functions + /// used in the IR. Each found external variable is added to the + /// struct, and each external function is resolved in place, its call + /// replaced with a call to a function pointer whose value is the + /// address of the function in the target process. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Write an initializer to a memory array of assumed sufficient + /// size. + /// + /// @param[in] data + /// A pointer to the data to write to. + /// + /// @param[in] initializer + /// The initializer itself. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); + + //------------------------------------------------------------------ + /// Move an internal variable into the static allocation section. + /// + /// @param[in] global_variable + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInternalVariable (llvm::GlobalVariable *global_variable); + + //------------------------------------------------------------------ + /// Handle a single externally-defined variable + /// + /// @param[in] value + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleVariable (llvm::Value *value); + + //------------------------------------------------------------------ + /// Handle a single externally-defined symbol + /// + /// @param[in] symbol + /// The symbol. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleSymbol (llvm::Value *symbol); + + //------------------------------------------------------------------ + /// Handle a single externally-defined Objective-C class + /// + /// @param[in] classlist_reference + /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" + /// where n (if present) is an index. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleObjCClass(llvm::Value *classlist_reference); + + //------------------------------------------------------------------ + /// Handle all the arguments to a function call + /// + /// @param[in] C + /// The call instruction. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleCallArguments (llvm::CallInst *call_inst); + + //------------------------------------------------------------------ + /// Resolve variable references in calls to external functions + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveCalls (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// Remove calls to __cxa_atexit, which should never be generated by + /// expressions. + /// + /// @param[in] call_inst + /// The call instruction. + /// + /// @return + /// True if the scan was successful; false if some operation + /// failed + //------------------------------------------------------------------ + bool + RemoveCXAAtExit (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveExternals (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A basic block-level pass to excise guard variables from the code. + /// The result for the function is passed through Clang as a static + /// variable. Static variables normally have guard variables to + /// ensure that they are only initialized once. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a load to a guard variable to return constant 0. + /// + /// @param[in] guard_load + /// The load instruction to zero out. + //------------------------------------------------------------------ + void + TurnGuardLoadIntoZero(llvm::Instruction* guard_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RemoveGuards (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A module-level pass to allocate all string literals in a separate + /// allocation and redirect references to them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all literals that will be + /// allocated as statics by the JIT (in contrast to the Strings, + /// which already are statics) and synthesize loads for them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStaticLiterals (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to make all external variable references + /// point at the correct offsets from the void* passed into the + /// function. ClangExpressionDeclMap::DoStructLayout() must be called + /// beforehand, so that the offsets are valid. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceVariables (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to remove all global variables from the + /// module since it no longer should export or import any symbols. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + StripAllGVs (llvm::Module &llvm_module); + + class StaticDataAllocator { + public: + StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); + lldb_private::StreamString &GetStream() + { + return m_stream_string; + } + lldb::addr_t Allocate(); + + lldb::TargetSP + GetTarget(); + private: + lldb_private::IRExecutionUnit &m_execution_unit; + lldb_private::StreamString m_stream_string; + lldb::addr_t m_allocation; + }; + + /// Flags + bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved + std::string m_func_name; ///< The name of the function to translate + lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) + lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. + llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. + std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the module being processed, or NULL if there is no module. + lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls + StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings + llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type + llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type + llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. + lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed + + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. + bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) + + llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. + + //------------------------------------------------------------------ + /// UnfoldConstant operates on a constant [Old] which has just been + /// replaced with a value [New]. We assume that new_value has + /// been properly placed early in the function, in front of the + /// first instruction in the entry basic block + /// [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old + /// in those uses with New. Where those uses are constants, the + /// function generates new instructions to compute the result of the + /// new, non-constant expression and places them before + /// FirstEntryInstruction. These instructions replace the constant + /// uses, so UnfoldConstant calls itself recursively for those. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + + class FunctionValueCache { + public: + typedef std::function <llvm::Value *(llvm::Function *)> Maker; + + FunctionValueCache (Maker const &maker); + ~FunctionValueCache (); + llvm::Value *GetValue (llvm::Function *function); + private: + Maker const m_maker; + typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; + FunctionValueMap m_values; + }; + + FunctionValueCache m_entry_instruction_finder; + + static bool + UnfoldConstant (llvm::Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder); + + //------------------------------------------------------------------ + /// Construct a reference to m_reloc_placeholder with a given type + /// and offset. This typically happens after inserting data into + /// m_data_allocator. + /// + /// @param[in] type + /// The type of the value being loaded. + /// + /// @param[in] offset + /// The offset of the value from the base of m_data_allocator. + /// + /// @return + /// The Constant for the reference, usually a ConstantExpr. + //------------------------------------------------------------------ + llvm::Constant * + BuildRelocation(llvm::Type *type, + uint64_t offset); + + //------------------------------------------------------------------ + /// Commit the allocation in m_data_allocator and use its final + /// location to replace m_reloc_placeholder. + /// + /// @param[in] module + /// The module that m_data_allocator resides in + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CompleteDataAllocation (); + +}; + +#endif // liblldb_IRForTarget_h_ diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 23ac29ebe80..cd6ece297ed 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Expression/ASTDumper.h" +#include "Plugins/ExpressionParser/Clang/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 4db11b26845..34a2d4b3930 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -25,7 +25,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index d3195edffb9..7f6cf3fa42e 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -70,12 +70,9 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Expression/ASTResultSynthesizer.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Expression/ClangFunctionCaller.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h" +#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp index f5df97c9c50..aab4bd31a03 100644 --- a/lldb/source/Target/ABI.cpp +++ b/lldb/source/Target/ABI.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index dc478bb08c1..1ba10f41c38 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -31,10 +31,10 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangASTSource.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" |